Prompt caching lets the API store a processed copy of a stable prompt prefix — your system prompt, tool definitions, a long document — so subsequent requests that start with the same bytes don't pay full price to reprocess it. But "caching" is two distinct billable operations. Writing a prefix into the cache costs more than normal input; reading it back costs a tenth of normal input. Understanding the split is essential before you can tell whether caching is saving you money or quietly costing you extra.
The multipliers
You mark cacheable content with "cache_control": {"type": "ephemeral"}, giving a 5-minute default lifetime, or add "ttl": "1h" for a 1-hour cache. Against your model's base input price:
| Operation | Multiplier | Opus 4.8 ($5/MTok base) | Haiku 4.5 ($1/MTok base) |
|---|---|---|---|
| 5-minute cache write | 1.25× | $6.25 / MTok | $1.25 / MTok |
| 1-hour cache write | 2× | $10 / MTok | $2 / MTok |
| Cache read (hit) | 0.1× | $0.50 / MTok | $0.10 / MTok |
The break-even arithmetic follows directly: a 5-minute cache pays for itself after a single read (1.25 + 0.1 = 1.35× versus 2× for two uncached passes), while a 1-hour cache needs at least two reads. If a prefix is used exactly once, caching it is pure overhead — you paid 1.25× for nothing.
What shows up in the usage object
Every response reports three input-side counters, and total input is the sum of all three:
cache_creation_input_tokens— tokens written to the cache on this request (billed at the write multiplier);cache_read_input_tokens— tokens served from an existing cache entry (billed at 0.1×);input_tokens— only the tokens after the last cache breakpoint, billed at the normal rate.
That last definition surprises people: on a cache hit, input_tokens can be tiny even though the model processed a huge prompt. Any cost dashboard that multiplies input_tokens by the list price will understate spend on cache-write-heavy days and overstate savings on read-heavy ones — track all three fields separately.
resp = client.messages.create(model="claude-opus-4-8", max_tokens=512,
system=big_system_prompt, messages=msgs,
cache_control={"type": "ephemeral"})
u = resp.usage
total_in = u.input_tokens + u.cache_creation_input_tokens \
+ u.cache_read_input_tokens
hit_rate = u.cache_read_input_tokens / max(total_in, 1)
print(f"cache hit rate: {hit_rate:.0%}")
Tracking cache efficiency
A healthy caching setup shows a large one-time cache_creation_input_tokens spike followed by requests dominated by cache_read_input_tokens. Two ratios are worth alerting on. The hit rate (reads divided by total input) tells you whether requests are actually matching the cached prefix — caching is a strict byte-for-byte prefix match, so a timestamp or non-deterministic JSON serialization in the system prompt silently drops it to zero. The write-to-read ratio catches the opposite failure: constant rewrites mean something near the top of your prompt keeps changing and invalidating everything after it.
There's also a rate-limit bonus hiding here: for most models, cache reads do not count toward your input-tokens-per-minute limit, while normal input and cache writes do. Anthropic's rate-limit docs give the example of a 2M ITPM limit effectively processing 10M input tokens per minute at an 80% cache hit rate — so good caching buys throughput headroom, not just dollars.
Platform notes
Prompt caching with both durations works on the Claude API, Claude Platform on AWS, Google Cloud, and Microsoft Foundry. Amazon Bedrock supports explicit cache_control breakpoints but not the automatic top-level caching mode, and Bedrock and Google Cloud isolate caches at the organization level rather than per workspace. Multipliers stack with other pricing modifiers, including the Batch API's 50% discount.
Where to go next
For the other half of the token bill, read Input vs Output Tokens. Cache mechanics in depth are covered in Prompt Cache Mechanics, and the cost framing in Prompt Caching Costs.