How the cache works

Why your usage breakdown is mostly cache reads, what makes text reusable, how long it survives, and what silently breaks it.

TL;DR
  1. Two unrelated things are both called "the cache". The KV cache is internal, automatic, and free. Prompt caching is the billed feature you control. This page is mostly about the second.
  2. Processing your prompt is expensive, and every conversational turn re-sends the same opening text. Prompt caching lets the server skip re-processing that repeated opening.
  3. It only works from the very start of the prompt forward, up to the first difference. One changed character early on and everything after it must be redone.
  4. You mark where to save with cache_control. Saving costs 25% extra once; reading back costs 90% less, every time after.
  5. A saved entry lives 5 minutes by default, and reading it resets that clock for free. So an active session stays cheap indefinitely, but a 10-minute gap makes caching cost more than not caching.
  6. If both cache counters in the response come back zero, caching silently didn't happen. That's the first thing to check.

Jargon gets defined on first use, and there's a glossary at the end. If you haven't read the first document, the one thing you need from it is that the model processes text left to right and each position can only see what came before it.

What a request is made of

Everything later depends on knowing the shape of what you send, so start there. A request to the API is a JSON document assembled from discrete pieces, each called a content block:

{
  "tools":  [ {tool definition}, {tool definition}, ... ],   ← blocks
  "system": [ {a chunk of instructions}, ... ],              ← blocks
  "messages": [
     {"role":"user",      "content":[ {text block} ]},
     {"role":"assistant", "content":[ {text block}, {tool request} ]},
     {"role":"user",      "content":[ {tool result} ]},
     ...
  ]
}

A block is one indivisible item: a single tool definition, one chunk of system instructions, one message's text, one tool result, one image. A long conversation with tool use is easily a hundred blocks. The count matters later, so it's worth having the picture.

The server flattens all of this into one long sequence of tokens, in a fixed order: tools first, then system, then messages. That flattened sequence is what the model actually sees.

Two more terms, both used constantly below:

The two caches

Both names are in common use and they mean different things:

KV cacheprompt caching
what it isKey and value vectors held in GPU memory while one request runsProcessed prefix state kept between requests so it can be reused
lifetimeThe request5 minutes, or 1 hour if you pay for it
you control it?No — always on, invisibleYes — via cache_control
on your bill?NoYes — two dedicated line items

They rest on the same underlying fact, which is why the naming collides. The next two sections cover that fact; everything after is about the billed one.

Why processing a prompt is expensive

Serving a request splits into two phases with quite different characteristics.

Prefill is processing your prompt. All its tokens go through all the layers together — large matrix multiplies, GPU saturated, limited by arithmetic throughput. Along the way, every token's key and value vector at every layer gets computed and held in memory. Prefill is what you wait through before the first output token appears.

Decode then produces output one token at a time. Each new token computes its own query, key and value, attends over all the stored keys and values from before, and appends its own. Only one token wide, so the multiplies are thin and the hardware spends most of its time moving memory rather than computing. Memory-bound rather than compute-bound — and that gap is roughly why output tokens are priced about five times input tokens.

The stored keys and values are the KV cache. Without it, generating token n would mean recomputing attention over all n−1 previous tokens from scratch: quadratic work instead of linear. It isn't optional, isn't configurable, and never appears on your bill.

PREFILL — your whole prompt, all at once one parallel pass · this is the wait KV cache key and value vectors, every token × every layer DECODE — output, one token at a time reads all of it, appends one, repeats at scale this cache can exceed the size of the model weights itself
Prompt caching, coming next, is essentially the idea of not throwing the top half of this diagram away when the request finishes.

Why a prefix can be reused

Here is the load-bearing fact, and it follows directly from the causal mask in the first document:

A token's key and value vectors depend only on the tokens at or before it. Nothing later can affect them, because no position is allowed to see past itself.

So if two requests begin with byte-identical text, the processed state for that shared opening stretch is identical too — not similar, identical. It can be computed once, saved, and handed to the second request. The expensive prefill over that stretch never runs again.

That is prompt caching. Three consequences fall straight out, and between them they explain nearly every caching surprise:

the second request: what gets reused, what gets redone
Drag the divergence point. Everything left of it is reused at one tenth the input price; everything right of it is full-price prefill no matter how similar it looks to last time. Watch how fast the saving collapses as the difference moves earlier — that's why a per-request timestamp in a system prompt is such an expensive habit.

Telling it what to save

Saving doesn't happen automatically. You mark a content block with cache_control, and the API saves the state of everything from the start of the prompt up to and including that block. That marker is called a cache breakpoint:

system=[
    {"type": "text", "text": WHOLE_STYLE_GUIDE,
     "cache_control": {"type": "ephemeral"}},     ← the breakpoint
]

("ephemeral" is currently the only type; it just means the entry expires rather than persisting.)

What gets stored is keyed by a hash of the whole prefix ending at that block. On a later request the API hashes the prefix at your breakpoint and looks for a stored entry with the same hash. Same hash means byte-identical opening text, which means the saved state is valid.

Three rules govern the rest, and misreading rule 2 is the usual cause of "I turned on caching and nothing happened":

  1. Saves happen only at your breakpoint. Marking a block stores exactly one entry. Nothing is stored at any earlier position.
  2. Lookups search backward for entries that earlier requests saved. If the hash at your breakpoint doesn't match anything, the API steps back one block at a time, hashing the shorter prefix at each position, looking for a hit. It is hunting for previously saved entries — not for stable-looking content.
  3. That backward search covers 20 blocks. If nothing matches within 20 positions, it gives up.

The mistake almost everyone makes

Say your prompt has a large static system context in blocks 1–5, and block 6 holds a timestamp plus the user's message. You put the breakpoint on block 6, since it's last:

request 1   hash(blocks 1..6) saved            ← the hash includes the timestamp
request 2   hash(blocks 1..6) is different → no match
            step back: block 5, 4, 3, 2, 1
            — but nothing was ever saved at those positions
            result: full-price prefill, plus another useless save

You pay the 25% save premium on every single request and never once get a read. The backward search can't rescue you: it only finds things earlier requests saved, and saves only happen at breakpoints.

The fix is one line — move cache_control to block 5, the last block that stays identical across requests. Then every subsequent request matches on the first try.

The rule to remember: put the breakpoint on the last block that is byte-identical across the requests you want to share a cache. For a static opening with a varying tail, that's the end of the static part, not the last block overall.

Using more than one

You get four breakpoints, and they cost nothing — you're billed on tokens saved and tokens read, not on markers. Two reasons to use several: caching sections that change at different rates (tool definitions rarely, reference documents daily), and long conversations, where each turn appends blocks until your breakpoint drifts more than 20 blocks past the last save and the backward search can no longer reach it. A second breakpoint further back gives it something to find.

Or let the API place it

For a plain growing conversation, put cache_control at the top level of the request and the breakpoint advances by itself as turns accumulate:

response = client.messages.create(
    model="claude-opus-5",
    max_tokens=1024,
    cache_control={"type": "ephemeral"},   # automatic placement
    system=SYSTEM_PROMPT,
    messages=history,
)

It puts the breakpoint on the last cacheable block — so it walks into exactly the trap above whenever your last block is the one that varies. Right default for a chat transcript; wrong for a prompt with a volatile tail.

How long a saved entry lives

Five minutes by default. Reading an entry resets that clock at no charge, so an active session stays warm indefinitely without ever paying a second save. The clock starts when the request that touches the entry begins, not when its response finishes — so a four-minute streaming response leaves only about a minute of usable life once it completes.

Send a request to start the clock, then wait and send another.
A 30,000-token prefix on Claude Opus 5 with the default 5-minute TTL. Green bands are windows where the entry is alive. Send requests a minute apart and the cost per call collapses; wait seven minutes and it starts over with a full-price save. Since a save costs 25% more than plain input, a cache that never gets read is strictly worse than no cache at all.

When the hour is worth buying

A 1-hour TTL is available as an explicit opt-in, and costs double base input on the save:

"cache_control": {"type": "ephemeral", "ttl": "1h"}

The break-even arithmetic is simple. A 5-minute save carries a 0.25× premium and each read saves 0.9×, so one read pays it back. A 1-hour save carries a 1.0× premium, so it needs two reads before it's ahead. If your calls come more often than every five minutes, the standard cache refreshes for free and the hour buys nothing. It earns its keep in the awkward zone — gaps longer than five minutes but shorter than an hour. A side-agent that runs for eight minutes; a user who steps away for coffee mid-conversation.

If you mix the two in one request, all 1-hour breakpoints must come before any 5-minute ones.

What this costs

Three prices, all quoted per million tokens, all derived from the model's base input price:

Only the unchanging opening is modelled here — the per-request tail and the output are the same under all three strategies, so they'd just add a constant. Push the gap past five minutes and watch the 5-minute column flip from cheapest to most expensive.

Reading your usage numbers

The response reports three separate input counts, and the trap is that the one called input_tokens is not your total. It counts only the tokens after your last breakpoint.

cache_read_input_tokens       tokens reused from a saved entry
cache_creation_input_tokens   tokens saved to a new entry on this call
input_tokens                  tokens after the breakpoint, cached neither way

total input  =  the three added together
"usage": {
  "cache_read_input_tokens":     29800,   // reused, 0.1× price
  "cache_creation_input_tokens":   240,   // saved now, 1.25× price
  "input_tokens":                   62,   // after breakpoint, full price
  "output_tokens":                 503
}
This is a healthy warm agentic session: a large read, a small save covering whatever was appended since the last call, and a handful of genuinely new tokens. If input_tokens looks impossibly small next to what you sent, that's the feature working. It also affects rate limits, since cache reads aren't counted against them.
The diagnostic that answers most questions. If cache_creation_input_tokens and cache_read_input_tokens are both zero, no caching happened — and no error was raised. Usual causes: the prompt is below the minimum cacheable length, the cache_control field is missing, or something between you and the API stripped it. If you reach the API through a gateway or corporate proxy, this pair of fields is the cheapest possible test: send the same request twice a few seconds apart and check whether the second one reads.

Minimum cacheable length

Below the threshold, cache_control is silently ignored. No error, no caching, no indication except those two zeroed counters.

minimummodels
512Opus 5, Fable 5 / 5.1, Mythos 5 / 5.1
1,024Opus 4.8, Opus 4.1, Opus 4, Sonnet 5, Sonnet 4.6, Sonnet 4.5, Sonnet 4
2,048Opus 4.7, Haiku 3.5, Mythos Preview
4,096Opus 4.6, Opus 4.5, Haiku 4.5

If you're just short, padding the cached region up to the threshold is usually worth it — reads are cheap enough that crossing the line repays the extra tokens quickly.

What breaks it

Because the flattening order is tools, then system, then messages, a change at one level invalidates that level and everything after it. ✘ means the cache for that section is lost.

changetoolssystemmsgswhy
any tool definition✘✘✘tools come first, so editing one name or description invalidates the entire prompt
web search on/off✔✘✘quietly modifies the system prompt
citations on/off✔✘✘likewise
tool_choice✔✔✘rendered into the message section only
adding or removing an image✔✔✘anywhere in the prompt, not just near the change
thinking configurationmodel-specificmodel-specific✘the mode and token budget get written into the prompt text
effort settingmodel-specificmodel-specific✘same mechanism; setting it explicitly to the default changes nothing

and the non-obvious ones

Warming it in advance

If the first user request of the day shouldn't have to absorb the cold-prefill wait, you can pay for the save ahead of time using max_tokens: 0. The API reads the prompt, saves the entry, and returns immediately with an empty response and no output tokens billed.

client.messages.create(
    model="claude-opus-5",
    max_tokens=0,
    system=[{"type": "text", "text": SYSTEM_PROMPT,
             "cache_control": {"type": "ephemeral"}}],
    messages=[{"role": "user", "content": "warmup"}],
)

Put the breakpoint on the shared opening, not on the placeholder message — otherwise the entry is keyed to the placeholder and your real traffic won't match it. This is also why automatic placement is wrong here. Match your thinking and effort settings to the real requests too, since those get written into the prompt. And the TTL still applies: re-warm inside the window, or buy the hour.

Checklist

  1. Order the prompt: tools, system, static reference material, then volatile content. Nothing time-varying above the breakpoint.
  2. Put cache_control on the last block that's byte-identical across the requests meant to share a cache.
  3. Check the cached region clears your model's minimum length.
  4. Look at cache_read_input_tokens on the second request. Both counters zero means caching never engaged.
  5. Hold tool_choice, image presence, thinking config and effort constant across a session.
  6. Reach for the 1-hour TTL only when gaps genuinely exceed five minutes but stay under an hour.
  7. Add a second breakpoint further back once a conversation grows more than 20 blocks past the last save.
  8. Let the first request of a new prefix finish before fanning out in parallel.

Glossary

content blockOne indivisible piece of a request: a tool definition, a chunk of system text, a message, a tool result, an image.
prefixAn opening stretch of the token sequence, counted from the very first token.
prefillThe phase that processes your prompt. Compute-bound; the wait before the first output token.
decodeThe phase that generates output, one token at a time. Memory-bound.
KV cacheKeys and values held in GPU memory during one request. Automatic, unbilled.
prompt cachingSaving processed prefix state between requests. Billed, and under your control.
cache breakpointA cache_control marker on a block, saying "save everything up to here".
ephemeralThe only cache type. Means the entry expires rather than persisting.
TTLTime-to-live: 5 minutes by default, 1 hour as a paid option.
cache write / saveCreating an entry. Costs 1.25× base input, once.
cache read / hitReusing an entry. Costs 0.1× base input, and refreshes the TTL for free.
lookback windowThe 20 blocks the API steps back through searching for a previously saved entry.
pre-warmingPaying for a save in advance with max_tokens: 0, so real traffic starts warm.

sources

  • Prompt caching — Anthropic's reference page. Every price, threshold and invalidation rule above comes from here; check it before acting on any of this, since the numbers move.
  • Cache diagnostics (beta) — has the API compare consecutive requests and report exactly where the prefix diverged. Faster than bisecting by hand.
  • Coding the KV cache from scratch — Sebastian Raschka, for the mechanism underneath in ~100 lines of readable Python.
  • Bedrock prompt caching — if you go via Bedrock, the minimums, usage field names and failure behaviour are AWS's, not Anthropic's.

Prices and thresholds verified against Anthropic's documentation on 2 September 2026. They change; the mechanism doesn't.