Your prompt cache can miss on every request and nothing will warn you
Both Claude and the OpenAI API bill cached input tokens at roughly a tenth of the regular price, and both fail silent — a cache miss produces no error, just a full-price invoice. One field in the API response tells you whether you are collecting the discount. Here are the exact fields to check, the break-even math, and the five configuration mistakes that make a cache miss on every single request.
If you ship anything on a metered LLM API — a support assistant, an agent, a RAG endpoint — every request re-sends the same system prompt and the same tool definitions. Both Claude and the OpenAI API will bill those repeated tokens at about a tenth of the normal input price through prompt caching. Claude bills cache reads at 0.1x the base input rate; on GPT-5.6-Sol, cached input is $0.50 per million tokens against $5.00 regular, per OpenAI's current pricing page.
The catch is that neither API will ever tell you the cache missed. There is no error, no warning header, no dashboard alert. A prompt that is structured wrong caches nothing, forever, and the only symptom is an input bill ten times larger than it needs to be. The fix starts with reading one field.
Read the usage object before you change anything
Take one real response from your production traffic and look at the usage block.
On the Claude API, three fields matter:
"usage": {
"cache_read_input_tokens": 3900,
"cache_creation_input_tokens": 0,
"input_tokens": 214
}
cache_read_input_tokens is what you retrieved at 0.1x price. cache_creation_input_tokens is what you wrote to the cache this request. input_tokens is what you paid full price for. If both cache fields are zero on a mature, high-traffic prompt, caching is not happening at all — and per Anthropic's docs that is exactly how a too-short or misconfigured prompt behaves: silently.
On the OpenAI API, the field is cached_tokens — inside usage.prompt_tokens_details on Chat Completions, or usage.input_tokens_details on the Responses API. Caching there is automatic for prompts of 1,024 tokens or longer, so a cached_tokens: 0 on a long prompt under steady traffic means the structure is defeating it.
Sixty seconds of looking at one response tells you which world you are in. Most teams have never looked.
What the discount is worth
Numbers verified against both providers' pricing pages this week:
| Regular input | Cached read | Cache write | |
|---|---|---|---|
| Claude (all current models) | 1x | 0.1x | 1.25x (5-min TTL) or 2x (1-hour TTL) |
| GPT-5.6 family | 1x | 0.1x | 1.25x |
On Claude the write premium pays for itself by the second request: one write plus one read costs 1.35x a single uncached send, against 2x for sending the same tokens cold twice. Every read after that costs 90 percent less than an uncached send. Concrete case: a support assistant with a 4,000-token stable prefix (system prompt plus tool definitions) serving 20,000 requests a day on Sonnet 5 at $2 per million input tokens. Uncached, that prefix costs 80 million tokens a day, or $160 — roughly $4,800 a month. With the cache hitting, the same prefix reads back at $0.20 per million: $16 a day, under $500 a month. Same model, same output quality, same latency or better. The only variable is whether the cache hits.
Five ways the cache misses without telling you
1. Variable content sits early in the prompt. Both caches are prefix-based: the provider hashes your request from the top and reuses the computed work only while the prefix matches the previous request exactly. One changed token invalidates everything after it. The classic mistake is a timestamp, a user name, or a session ID interpolated near the top of the system prompt — every request now has a unique prefix and a zero percent hit rate. Both providers give the same instruction: static content first, variable content last. Move the per-request context (user data, retrieved chunks, the incoming message) to the end, after the stable instructions and examples.
2. The prompt is below the minimum and nothing said so. Claude will not cache prompts shorter than a per-model minimum: 1,024 tokens on Sonnet 5 and Opus 4.8, 512 on Fable 5, and 4,096 on Haiku 4.5. OpenAI's floor is 1,024 tokens across the board. Below the floor, the request succeeds normally and both cache fields read zero. If your prefix is 800 tokens, the fix can be as blunt as moving your few-shot examples into the system prompt so the stable prefix clears the threshold.
3. The prefix includes more than you think. On the Claude API the cached prefix is hashed in a strict order: tool definitions, then system prompt, then messages. Anything that varies at an earlier level invalidates every level after it. Changing the tool_choice parameter or adding an image invalidates the message-level cache even when the system prompt is byte-identical. Toggling web search invalidates from the tools level down. The common production version of this mistake is assembling the tool list dynamically per request — different tool subsets mean different prefixes, and the cache never warms.
4. Your traffic is slower than the TTL. Claude's default cache entry lives 5 minutes, refreshed at no cost on every read. Steady traffic keeps it warm indefinitely; requests spaced further apart than the TTL pay the 1.25x write on every call and never read once — which makes a misconfigured cache slightly more expensive than no cache. For lower-frequency workloads Claude offers a 1-hour TTL at 2x write cost, which still breaks even after the second read within the hour. On GPT-5.6-family models the cache persists at least 30 minutes; on older OpenAI models, entries can evict after 5 to 10 minutes of inactivity.
5. The Claude breakpoint sits on the wrong block. Claude caching is opt-in via cache_control markers, and the marker means "cache everything up to and including this block." Placing it on a block that changes per request — the last user message is the usual victim — produces a hash that never matches any previous request. Put the breakpoint on the last stable block instead, or set cache_control: {"type": "ephemeral"} at the top level of the request and let the API place the breakpoint automatically. One more edge worth knowing: a cache entry only becomes available once the first response has started, so a parallel burst of identical cold requests all pay the write price. Warm the cache with one request before fanning out.
For high-volume OpenAI traffic there is one extra lever: the prompt_cache_key parameter routes requests with the same key to the same cache, and OpenAI recommends keeping each key under roughly 15 requests per minute, partitioning keys above that.
Stack it with the batch discount for offline work
Everything above applies to live traffic. For work that can wait — evals, backfills, bulk classification — both providers run a Batch API at 50 percent off all token prices, and the discounts stack: a cached read inside a batch gets both the 50 percent batch discount and the 90 percent cache discount. Anthropic's batch docs note that cache hits inside batches are best-effort (observed hit rates range from 30 to 98 percent depending on traffic) and recommend the 1-hour TTL for batch workloads, since a batch can take longer than 5 minutes to schedule.
Make the hit rate a metric, not a mystery
The reason this whole class of savings goes uncollected is that nobody owns the number. Log cache_read_input_tokens / (cache_read_input_tokens + cache_creation_input_tokens + input_tokens) per request and put it on the same dashboard as your latency. A mature single-prompt service should sit well above 50 percent; a number near zero is a bug with a dollar cost attached.
Do this before you consider downgrading models to save money. Cheaper-model routing is a real lever — we covered where it applies inside Claude Code — but it trades capability for price. A cache hit trades nothing. With usage-based pricing spreading across the frontier labs, the teams that treat token flow as an engineering surface, starting with one field in the usage object, are the ones whose bills stay flat while their traffic grows.
Pricing, minimums, TTLs, and field names verified against Anthropic's prompt caching and batch processing documentation and OpenAI's prompt caching guide and pricing page on 2026-07-16.
Get the next post when it ships
One email on Sunday with the new post and a short list of what shipped that week — new guides, tool updates, and a couple of links worth reading.