By the end you can say what the cache stores and why a repeated prefix on the Council bills at about a tenth.
Every call to the model resends the whole prompt. The model keeps no memory between calls — so if you want it to know your instructions and tools, you send them again, in full, on every single call.
In the Council — our running example, a panel of model "members" that each take a turn on a question — the big system prompt and the long tool list go up on every member turn. And you pay to process all of it, every time. The brief at the end might be two lines; the opening might be ten thousand tokens.
Prompt caching keeps the processed opening ready on the server. The next call that starts with the exact same opening doesn't re-pay to process it — it pays about a tenth to reuse it. The big shared part gets cheap; only the new part at the end is billed at full price.
Think of it like… a barista who knows your usual. The first time, you explain the whole order in detail — and you pay for that. After that you just say "the usual" and they skip straight ahead. Change one word ("oat milk today") and they re-take the whole order from the top. Unlike a barista, though, the cache forgets after a few minutes of no orders — so the savings only last while you keep coming back.
Caching is a prefix match. The cache key is the exact bytes of your request up to a cache_control breakpoint. If those bytes match a previous request byte-for-byte, the model reuses the work it already did on that prefix.
A cache read is billed at roughly 0.1x the normal input rate and shows up as usage.cache_read_input_tokens. A cache write (the first call, which stores the prefix) costs 1.25x for the 5-minute TTL or 2x for the 1-hour TTL, and shows up as usage.cache_creation_input_tokens. Everything that isn't cached is ordinary input_tokens at the normal rate.
The cache is scoped to the model: a prefix cached on one model is not reused by another. Change the model and you start a fresh cache.
One marker turns it on. You add cache_control to the end of the part you want cached — here, the Council member's big system prompt — and the next identical call reuses it.
response = client.messages.create( model="claude-fable-5", max_tokens=1024, system=[ { "type": "text", "text": MEMBER_SYSTEM_PROMPT, # the big, shared opening "cache_control": {"type": "ephemeral"}, # cache everything up to HERE } ], messages=[{"role": "user", "content": brief}], # the changing tail ) # On a cache hit, this is > 0: print(response.usage.cache_read_input_tokens)
Send the same request twice. The first call stores the prefix: cache_creation_input_tokens is non-zero, cache_read_input_tokens is 0. The second identical call is a hit: cache_read_input_tokens is non-zero. Your total prompt is always input_tokens + cache_creation_input_tokens + cache_read_input_tokens.
You can place up to 4 breakpoints per request. And the cached prefix must clear a minimum size or it's silently not cached: about ~2048 tokens on Fable 5 / Sonnet 4.6, and ~4096 on Opus 4.8 / 4.7 / 4.6. Below that threshold, you'll see no cache writes or reads at all.
Poke the three buttons below to watch the same Council turn billed three ways. Units are illustrative input-token-equivalents: a shared prefix of 10,000 and a per-turn brief of 400.
Total billed: — input-token-equivalents
——