Prompt Caching deep — kỹ thuật giảm 90% phí AI mà ít dev biết tận dụng
Anthropic prompt caching launch tháng 8/2024 — cache prefix tĩnh, request thứ 2 chỉ tính 10% giá input. Hiểu 4 cache breakpoint, TTL 5 phút vs 1 giờ, hit rate optimization, pitfalls phổ biến để tận dụng max saving 80-95% cho production AI app.
Mục lục bài viết(32)

Memory hierarchy trong máy tính — register (nhanh nhất, đắt nhất) → L1/L2/L3 cache → RAM → SSD → HDD. Prompt caching trong LLM follow concept tương tự: cache intermediate attention state ở server, request lặp lại re-use → giảm 90% compute. Saving compound khi volume scale — production app có thể tiết kiệm $1000s/tháng từ caching đúng cách. Nguồn: Wikimedia Commons (CC BY-SA 4.0).
Hiểu đơn giản nhất
Bạn build AI chatbot. System prompt 5000 token (boilerplate, instruction, brand voice). Mỗi user query, gửi full system prompt + user message → AI process.
Không caching:
Request 1: process 5000 system + 200 user → cost $0.0165
Request 2: process 5000 system + 200 user → cost $0.0165 (lại process)
Request 3: process 5000 system + 200 user → cost $0.0165
...
Request 1000: total $16.50
5000 token cùng nhau process 1000 lần = waste compute.
Với prompt caching:
Request 1: process 5000 system + 200 user → cache 5000 → cost $0.021 (1.25x write)
Request 2: 5000 cached, only 200 user new → cost $0.003 (only user paid full)
Request 3: same as request 2 → cost $0.003
...
Request 1000: total $3.02 (vs $16.50 no cache) = save 82%
5000 token process 1 lần, reused 999 lần.
Cách hoạt động
LLM dùng "attention mechanism" tính relationship giữa token. Tính 5000 token là expensive (O(n²) complexity). Caching = lưu intermediate attention state ở server. Request sau:
- Server check hash của prefix
- Nếu match cache → load intermediate state → skip recompute
- Chỉ process token mới (user message, sau breakpoint)
- Bill 10% giá normal cho cached portion
| Phần prompt | No cache cost | Cached cost |
|---|---|---|
| Write cache (lần 1) | 1.0x base input | 1.25x base input |
| Cache read (lần 2+) | 1.0x base input | 0.1x base input |
| Output | 1.0x base output | 1.0x base output (unchanged) |
Saving 90% on cached portion. Net 80-85% with write overhead.
Tại sao bạn cần biết
- AI bill production blow up khi scale. 1000 user/ngày × system prompt 5000 token = $200/ngày = $6000/tháng. Caching = $1000/tháng. Diff $5000/tháng = $60k/năm.
- Setup chỉ 1 flag trong code.
cache_control: { type: "ephemeral" }— 5 dòng config saves 80%. - OpenAI auto-caching nhưng saving lower. Anthropic explicit caching cho higher control + higher saving.
- Critical cho RAG. RAG inject 10-50k context mỗi query → caching RAG context = massive saving.
- Tool use definitions cũng cache-able. 30+ tool defs (5-10k token) cached → save substantial cho agent app.
4 Cache breakpoint patterns
Pattern 1: System prompt only
Simplest setup:
const message = await client.messages.create({
model: "claude-sonnet-4-5",
system: [
{
type: "text",
text: longSystemPrompt, // 5000 token boilerplate
cache_control: { type: "ephemeral" }
}
],
messages: [{ role: "user", content: "Hello" }]
});System cached, messages variable per request. Saving 90% on system token.
Pattern 2: System + Tool definitions
Agent với many tools:
const message = await client.messages.create({
system: [
{ type: "text", text: systemPrompt, cache_control: { type: "ephemeral" } }
],
tools: [
{ name: "tool1", ..., cache_control: { type: "ephemeral" } },
{ name: "tool2", ... },
// ... 30 more tools
],
messages: [...]
});System + tools both cached (2 breakpoint). Tool definitions don't change between requests — perfect cache candidate.
Pattern 3: System + RAG context
RAG chatbot:
const message = await client.messages.create({
system: [
{ type: "text", text: systemPrompt, cache_control: { type: "ephemeral" } }
],
messages: [
{
role: "user",
content: [
{
type: "text",
text: ragContext, // 30k token retrieved docs
cache_control: { type: "ephemeral" }
},
{ type: "text", text: userQuery }
]
}
]
});3 breakpoint: system + RAG context + user query. RAG context retrieved fresh nhưng same retrieval pattern over 5 phút → cached.
Pattern 4: Multi-turn conversation
Long chat:
const message = await client.messages.create({
system: [{ type: "text", text: systemPrompt, cache_control: { type: "ephemeral" } }],
messages: [
{ role: "user", content: "Turn 1 query" },
{ role: "assistant", content: "Turn 1 response" },
{ role: "user", content: "Turn 2 query" },
{ role: "assistant", content: "Turn 2 response", cache_control: { type: "ephemeral" } },
// ... cached up to turn 2
{ role: "user", content: "Turn 3 query" } // New, not cached
]
});Cache up to specific turn. Turn N+1 reads cache, chỉ process turn mới.
TTL — 5 phút vs 1 giờ extended
Default ephemeral (5 phút)
cache_control: { type: "ephemeral" }- TTL 5 phút sau last access
- Cost write: 1.25x base
- Free
- Fit: chatbot real-time (user gửi liên tục)
Extended 1 giờ (Claude 3.5+)
cache_control: { type: "ephemeral", ttl: "1h" }- TTL 1 giờ
- Cost write: 2x base
- Fit: batch processing, eval, scheduled task
Quyết định
Request frequency > TTL → cache hit
Request frequency < TTL → cache miss (waste write cost)
5 phút TTL:
- User chat 1 query / 30s-2min → hit good ✓
- Cron job mỗi giờ → miss ✗
1 giờ TTL:
- Cron job mỗi 30 phút → hit ✓
- Daily batch → miss ✗ (consider không cache)
Hit Rate optimization — 7 tactic
Tactic 1: Move dynamic out of cache portion
// BAD: dynamic content trong system → invalidate cache
system: `You are bot. Current time: ${new Date()}. User: ${userId}.`
// GOOD: static system + dynamic in messages
system: `You are bot. ...` // ← cacheable
messages: [
{ role: "user", content: `Time: ${new Date()}. UserID: ${userId}. Query: ${query}` }
]Tactic 2: Standardize tool definitions
Đừng pass tools array khác order/version giữa request. Cache hash based on EXACT sequence:
// BAD: regenerate tools list mỗi request (object reference khác)
tools: regenerateTools(...)
// GOOD: const reference shared
const TOOLS = [...]; // Singleton
tools: TOOLSTactic 3: Batch similar request
Group user request từ similar context để hit cùng cache:
// BAD: round-robin different user
processRequests([user1, user2, user1, user3, user2]);
// → cache thrash
// GOOD: batch by user
processRequests([user1, user1, user1, user2, user2, user3]);
// → user1 hit cache 3 lầnTactic 4: Pre-warm cache
Daily cron job pre-warm cache cho upcoming heavy hour:
// 8am cron: pre-warm before 9am peak
await client.messages.create({
system: [{ type: "text", text: systemPrompt, cache_control: ... }],
messages: [{ role: "user", content: "warmup" }],
max_tokens: 10
});Cost: $0.05/warmup. Benefit: first user 9am hit cache instead of miss.
Tactic 5: Smaller cached portion
Cache phải > min size (1024-2048 token). Nếu prefix < min → split:
// BAD: prefix 800 token < min → no cache
system: "Short system prompt 800 token..."
// GOOD: extend with boilerplate to > min
system: "Short system + brand voice + examples 3000 token..."Padding với useful content (examples, guidelines) > 1024 → cache enabled.
Tactic 6: Monitor cache metrics
Response headers từ Anthropic API:
{
"usage": {
"input_tokens": 200, // Total input
"cache_creation_input_tokens": 0, // Write cost
"cache_read_input_tokens": 5000, // Read benefit
"output_tokens": 500
}
}Hit rate calculation:
const hitRate = usage.cache_read_input_tokens /
(usage.cache_read_input_tokens + usage.cache_creation_input_tokens);Target > 70% hit rate.
Tactic 7: TTL match request pattern
Plot histogram request gap → choose TTL.
< 5 phút between requests: ephemeral default
5-60 phút: extended 1h ($)
> 1 hour: probably skip caching
Pitfalls phổ biến
1. Cache key bao gồm dynamic content
Invalidate every request. Detection: monitor cache_read_input_tokens luôn 0.
2. Min size không đủ
< 1024 (3.x) / 2048 (4.x) token cached portion = ignored. Detection: cache header consistently 0.
3. Multi-region inconsistency
Anthropic deploy multi-region. Cache per-region. User route khác region → cache miss. Fix: pin client to single region.
4. Cache TTL hết giữa session
User idle 6 phút mid-conversation → cache miss next turn. Fix: extend TTL 1h cho long-session.
5. Tools list không deterministic order
// BAD: random order each call
tools: shuffle(toolList)
// GOOD: sorted consistent order
tools: [...toolList].sort((a, b) => a.name.localeCompare(b.name))6. System prompt template variable
// BAD: template substitution trong system
system: `Bot for ${tenantName}, day ${dayOfWeek}.`
// GOOD: parameterize via messages
system: "Bot per tenant + day"
messages: [{ role: "user", content: `Tenant: ${tenantName}, Day: ${dayOfWeek}. Query: ...` }]7. Cache cho 1-shot script
// One-time script — không cần cache (no reuse)
node generate-report-once.js // KHÔNG add cache_controlWrite cost 1.25x cho no benefit.
Ví dụ thực tế: vietcodex.com wiki gen caching
// Wiki content generation pipeline
const SYSTEM_PROMPT = `
You are VietCodex wiki writer...
[Brand voice 1000 token]
[Vietnamese style guide 1500 token]
[Cross-link strategy 1000 token]
[Schema requirements 800 token]
[FAQ format guide 500 token]
[Example output 700 token]
`; // Total ~5500 token
const TOOL_DEFS = [
{ name: "search_wikimedia", ... },
{ name: "verify_url", ... },
{ name: "check_cross_link", ... },
// ... 8 tools, ~3000 token total
];
// Generate 1 article
async function generateArticle(topic: string) {
return client.messages.create({
model: "claude-sonnet-4-5",
system: [{ type: "text", text: SYSTEM_PROMPT, cache_control: { type: "ephemeral" } }],
tools: [
...TOOL_DEFS.slice(0, -1),
{ ...TOOL_DEFS.at(-1), cache_control: { type: "ephemeral" } } // breakpoint after tools
],
messages: [
{ role: "user", content: `Write wiki article on: ${topic}` }
],
max_tokens: 6000
});
}
// Generate 20 article session
for (const topic of topics) {
await generateArticle(topic);
}
// Result:
// Article 1: $0.015 (write) + $0.090 output = $0.105
// Article 2-20: $0.003 (read) + $0.090 output = $0.093 each
// Total 20 article: $0.105 + 19 × $0.093 = $1.873
// Without caching:
// Each article: 5500 × $3/M + 3000 × $3/M + 6000 × $15/M = $0.0165 + $0.009 + $0.090 = $0.1155
// Total: 20 × $0.1155 = $2.31
// Saving: $2.31 - $1.873 = $0.44 (19%)Modest saving cho 20 article session. Caching shines khi volume scale — production chatbot 10k query/ngày saving compound massive.
Cái gì có thể sai
| Vấn đề | Triệu chứng | Cách fix |
|---|---|---|
| Cache miss luôn | cache_read_input_tokens = 0 | Check dynamic content trong cached portion |
| Cache size too small | Cache flag silent ignored | Verify > 1024 (3.x) or 2048 (4.x) token min |
| TTL hết quá sớm | Hit rate < 30% | Extend TTL 1h hoặc reduce request gap |
| Write cost > saving | Hit rate < 20% | Don't cache nếu volume thấp |
| Tools order random | Cache hash inconsistent | Sort tools deterministic |
| Multi-region cache miss | User routing khác region | Pin region trong client config |
| Long output không cache | Output không cacheable | Output luôn full price, expected |
| Stream interrupt mid-cache | Aborted before cache write | OK — cache write only on success |
Tóm tắt 1 dòng
Prompt caching (Anthropic) = cache prefix tĩnh, request thứ 2+ chỉ trả 10% giá input. Saving 80-90% on cached portion với 1 flag config. 4 breakpoint max: system + tools + RAG context + history. Min cache size 1024-2048 token. TTL default 5 phút ephemeral (free), extended 1 giờ (2x write cost). Hit rate target > 70% production. Pitfall: dynamic content trong cached portion = invalidate, non-deterministic tool order, size below min. OpenAI có auto-caching saving 50%, Anthropic explicit saving 90% — Anthropic win cho production high-volume.
Đọc tiếp
- AI Cost Management 2026 — caching là 1 trong 8 tactic — sister bài deep
- Context Window + Token economics — fundamentals token + pricing
- Multi-agent + Cost routing — caching combine với multi-agent
- Evals — cách đo AI output có tốt — eval cost tracking cần caching