Prompt caching on the Claude API: up to 90% off repeated input
TL;DR
Prompt caching stores your repeated prompt prefix; later reads cost about 10% of input price and don't count toward ITPM. Put static content first, place the breakpoint after the last static block, and watch cache_read_input_tokens.
Your chatbot has a 3,000-token system prompt, 2,000 tokens of tool definitions and 20,000 tokens of product documentation. Each user question is a few dozen tokens, but you pay for all 25,000 tokens in front of it on every request. Claude API's prompt caching solves exactly this: the repeated beginning of the prompt is stored, and later requests pay only about 10% of the input price for that part (even less on some newer models). This post covers how to enable it, how it's priced and the mistakes that make the cache "never hit".
Two ways to enable it
Automatic: add cache_control at the top level of the request; the system places the cache point on the last block and moves it forward as the conversation grows. Good for multi-turn chat.
{
"model": "claude-sonnet-5-5",
"max_tokens": 1024,
"cache_control": {"type": "ephemeral"},
"system": "You are a customer support assistant...",
"messages": [ ... ]
}
Manual (explicit breakpoints): put cache_control on individual blocks for precise control. Good when parts change at different rates.
"system": [
{
"type": "text",
"text": "...long system prompt + product docs...",
"cache_control": {"type": "ephemeral"}
}
]
Core rules
- Prefix order:
tools→system→messages. The cache covers everything before, including the block withcache_control. - At most 4 breakpoints per request (automatic caching takes one slot).
- Minimum length: prompts shorter than the model's threshold (512 to 4,096 tokens depending on the model) are not cached, and there's no error.
- 100% match: a single different character before the breakpoint is a miss.
Pricing and lifetime
| Type | Multiplier vs base input price | Notes |
|---|---|---|
| Cache write, 5-minute TTL (default) | 1.25× | TTL refreshes for free on each use |
| Cache write, 1-hour TTL | 2× | "ttl": "1h", good for sparse traffic |
| Cache read | 0.1× (default) | Lower still on some newer models such as Opus 5.5, Sonnet 5.5 |
Quick maths: writing once costs 25% extra, but a single re-read already breaks even. Cache multipliers stack with Batch API discounts. Beyond price, on most models cache-read tokens don't count toward the ITPM rate limit, so effective throughput rises significantly.
What breaks the cache?
| Change | What is lost |
|---|---|
| Tool definitions (name, description, parameters) | Everything |
| System prompt; toggling web search, citations | System + messages |
tool_choice, adding/removing images | Messages |
| Thinking parameters, request-level effort | Messages (more on some models) |
The classic mistake: a cache that never hits
- Breakpoint on changing content: for example a block with a timestamp "Today is 10:32:15" or the user's message. The hash never matches: you pay the 1.25× write every time and never read. Put the breakpoint on the last static block and move dynamic parts after it.
- Unstable JSON key order: some languages (Swift, Go) may shuffle key order in
tool_useinput, causing misses. - Parallel requests too early: the cache is only available after the first response starts. Fire 50 concurrent requests at once and none benefit; wait for the first.
- Too many blocks added in one turn: the system only looks back up to 20 blocks to find an earlier entry. Add a breakpoint nearby if one turn produces many blocks.
Checking the response
"usage": {
"input_tokens": 50, // after the last breakpoint, uncached
"cache_creation_input_tokens": 0, // just written to cache
"cache_read_input_tokens": 25000, // read from cache
"output_tokens": 310
}
Total input = cache_read + cache_creation + input_tokens. If both cache fields are always 0, the prompt is below the threshold or the breakpoint is in the wrong place.
How to apply it
- Dev: Order the prompt by stability: tools → system → documents → history → new question. Log the
cache_read/total input ratio per request. - Tech Lead: Ban timestamps and request IDs in the system prompt. Keep thinking/effort parameters fixed within a conversation.
- PM: For a chatbot with fixed documentation, caching is often the biggest cost cut that doesn't require changing models. Put "cache hit rate" on the cost dashboard.
Sources & references
- Prompt caching — Claude Docs
- Rate limits — Cache-aware ITPM — Claude Docs