Anthropic prompt caching, explained: TTLs, pricing, and the prefix rule
Prompt caching is the single biggest cost and latency lever on the Claude API: up to ~90% cheaper input and dramatically faster long-prompt responses. It's also easy to silently get zero benefit from. This is a compact, engineer-oriented reference: the one invariant, the pricing, the break-even math, and the mistakes that zero your hit rate.
The one invariant: exact prefix match
Everything about prompt caching follows from one rule: the cache is a prefix match on
the exact bytes of your rendered prompt. The request is rendered in a fixed order,
tools → system → messages, and the cache key is derived
from those bytes up to each cache_control breakpoint. One byte changed at position
N invalidates everything at and after N.
That's why appending a new message to a conversation is cheap (the prefix is untouched; only the tail is new), while editing your system prompt or reordering a tool is expensive (the change happens early, so everything downstream re-processes). And because the cached artifact is the model's internal state, the key also includes the model itself. See why switching models mid-session breaks the cache.
Pricing: writes cost extra, reads are 90% off
From Anthropic's prompt caching documentation:
| Operation | Multiplier | Example @ $3/M input (Sonnet) |
|---|---|---|
| Uncached input | 1× | $3.00 / M tokens |
| Cache write, 5-min TTL | 1.25× | $3.75 / M |
| Cache write, 1-hour TTL | 2× | $6.00 / M |
| Cache read | ~0.1× | $0.30 / M |
Break-even math
- 5-minute TTL: write + one read = 1.25× + 0.1× = 1.35×, versus 2× for two uncached sends. One hit and you're already ahead; every further hit is ~90% off.
- 1-hour TTL: write + two reads = 2× + 0.2× = 2.2×, versus 3× uncached. You need at least two hits to win, so reserve the long TTL for prefixes reused across gaps longer than 5 minutes (bursty traffic, scheduled jobs, long meetings between turns).
The TTL is refreshed every time the cache is read, so an active coding session keeps itself warm indefinitely. The 5-minute clock only matters when you walk away.
Mechanics worth memorizing
- Breakpoints: you place up to 4
cache_control: {"type": "ephemeral"}markers per request. A marker on the last system block caches tools + system together. In multi-turn conversations, mark the last message block. Earlier breakpoints remain valid read points as the conversation grows. - Minimum size: short prefixes silently don't cache. No error, just zero benefit. The minimum is model-dependent (roughly 1,024–4,096 tokens across current Claude models).
- Scope: the cache is keyed to your organization and the exact model. It's never shared across orgs or across models.
- Concurrency: a cache entry becomes readable only once the first response starts streaming. N identical parallel requests all pay full price; for fan-outs, fire one request, await the first token, then send the rest.
Not all changes are equal: the invalidation hierarchy
The API caches in tiers (tools, system, messages). A change only invalidates its own tier and everything after it:
| You changed… | What survives |
|---|---|
| Message content (appended a turn) | Tools + system + all prior turns |
tool_choice, images, thinking toggle | Tools + system |
| System prompt text | Tools only |
| Tool definitions (add/remove/reorder) | Nothing |
| The model | Nothing |
Silent cache killers (the audit list)
If cache_read_input_tokens is zero on repeated, seemingly-identical requests, one
of these is almost always the culprit:
datetime.now()/Date.now()interpolated into the system prompt, which changes the prefix on every request.- UUIDs or request IDs early in the prompt.
- Non-deterministic JSON serialization (unsorted keys, iterating a set) in tools or context.
- Per-user tool sets or conditional system sections: every variant is a distinct prefix.
- A prefix under the minimum cacheable size.
- And of course: a different
modelstring between requests.
The fix is always the same: keep stable content first, make it byte-deterministic, and push volatile content (timestamps, the user's actual question) after the last breakpoint.
Verifying: read the usage block
"usage": {
"input_tokens": 512, // uncached remainder, full price
"cache_creation_input_tokens": 2048, // written this request (1.25x)
"cache_read_input_tokens": 145600 // served from cache (0.1x)
}
Total prompt size is the sum of all three. A healthy long-running agent shows a large
cache_read_input_tokens, a small write, and a tiny uncached remainder. In Claude
Code, this is why marathon sessions are affordable at all.
Anthropic's team calls prompt caching "everything"
for agentic products, and
Claude Code enables it by default.
What this means for day-to-day agent use
- Long sessions are cheap while they stay warm. Keep turns coming (or accept a one-time rebuild after breaks).
- Don't edit the front of the prompt. Changing CLAUDE.md, MCP servers, or hooks mid-session re-processes everything after the change.
- Don't switch models mid-session. It's the only common action, along with tool changes, that invalidates every tier at once. Use one session per model instead (the pattern behind Model Shift's cache-safe gear tabs), or delegate to a subagent on the other model.
Multiple models, every cache warm
Model Shift runs each Claude/Codex model in its own persistent tab. Shift between them like gears without ever rebuilding a cache.
Get Model Shift for Mac ⇣Further reading: Why switching models mid-session breaks your prompt cache · A cache-safe multi-model workflow