
If your prompts reuse the same long context every call — system prompts, few-shot examples, RAG chunks, tool definitions — you are paying for those tokens ten times over. Anthropic's prompt caching cuts the cost of cached tokens by ~90% and the latency roughly in half. Most teams never turn it on. Here is the entire setup.
I audited a friend's production app last week. They were burning $11K/month on Claude Sonnet, 70% of which was re-sending the same 14K-token system prompt plus a 200-shot example block on every call. With caching, that 14K becomes ~$0.30 per million cached reads instead of $3. A 90% discount, applied to the biggest line item, dropped the bill to roughly $3K/month. Same product. No model swap, no fine-tune, no infra work.
Caching is opt-in. You mark which blocks should be cached, the API caches them for ~5 minutes (extendable to 1 hour with extended TTL), and subsequent reads of the same prefix are cheap.
Mark a block cacheable by adding a cache_control breakpoint. That is it.
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
system=[
{
"type": "text",
"text": LONG_SYSTEM_PROMPT, # 14K tokens, rarely changes
"cache_control": {"type": "ephemeral"} # <-- this line
}
],
messages=[{"role": "user", "content": user_input}],
)The same cache_control block works on individual messages and tool definitions. The API reads the prefix up to that breakpoint as the cache key.
Three rules I follow on every integration:
1. Put it on the longest stable prefix. System prompts first, then any few-shot examples, then the largest retrieved document. The cache reads as a contiguous prefix, so order matters. 2. Use one breakpoint per stable region. Multiple breakpoints on the same prefix waste cache slots. Anthropic allows up to 4, but you almost never want more than 2. 3. Do NOT cache the user message if it changes every call. The cache only helps if the prefix repeats. If you slap cache_control on the user's question, you pay cache write cost with zero read benefit.
For RAG pipelines, the pattern that works:
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": retrieved_doc_1, "cache_control": {"type": "ephemeral"}},
{"type": "text", "text": retrieved_doc_2, "cache_control": {"type": "ephemeral"}},
{"type": "text", "text": f"Question: {user_query}"}, # NOT cached
]
}
]Retrieved docs get cached when the same chunks show up again across requests. The user question stays uncached. You get the win without invalidating the cache on every call.
Read the usage block in the response. Cached reads show up separately:
print(response.usage)
# {'input_tokens': 14, 'cache_creation_input_tokens': 14000, 'cache_read_input_tokens': 14000, 'output_tokens': 412}If cache_read_input_tokens is zero, your breakpoint is in the wrong place or the prefix is not actually repeating. Common gotchas: dynamic timestamps inside the system prompt, retrieved docs being re-ranked per request, or per-user secrets getting injected above the cache line.
Prompt caching is the cheapest optimization in your stack. If you have any prompt over ~2K tokens that repeats more than twice in a 5-minute window, turn this on before you do anything else. Cost drops, latency drops, your quota headroom opens up. There is no reason not to ship it today.
— Mr. Technology