{"slug": "coding-agent-prompt-cache-miss-cost-what-breaks-the-prefix-and-how-to-find-it", "title": "Coding agent prompt cache miss cost: what breaks the prefix and how to find it", "summary": "A prompt cache miss on Claude Sonnet 5.5 or Opus 5.5 costs 25 times a cache hit and 1.25 times sending the same prefix uncached, at Anthropic's 19 October 2026 prices, according to an analysis of Anthropic's prompt-caching documentation. The analysis recomputed Rajesh Beri's 30-turn agent loop with a 20k-token prefix growing 1,500 tokens per turn at Sonnet 5.5 prices with five-minute writes: $2.72 uncached versus $0.41 cached, an 85% saving, while changing a tool description every turn raised the session to $3.36, 24% more than not caching. Anthropic cut Sonnet 5.5 cache reads from $0.20 to $0.10 per million tokens on 7 October 2026 with writes unchanged, doubling the miss-to-hit ratio from 12.5 to 25 and making a stable prefix more valuable.", "body_md": "# Coding agent prompt cache miss cost: what breaks the prefix and how to find it\n\nA prompt cache miss on Claude Sonnet 5.5 or Opus 5.5 costs 25 times what a cache hit costs on the same prefix, and 1.25 times what sending it uncached would have cost, at Anthropic's October 2026 prices. The first cause to rule out is a pause longer than the cache lifetime, which is five minutes on an API key. If your misses come within that window, something changed the prefix: the tool list, the model, the effort setting, a value in the system prompt, or an edit to earlier turns. Each leaves its own trace, and Claude Code now names most of them.\n\n## A cache miss shows up as reads near zero and writes near the whole prompt\n\nA prompt cache miss is a request that re-processes, at the write price, a prefix it could have read from cache. In the Anthropic API response, `cache_read_input_tokens` drops to zero or to the part before the change, and `cache_creation_input_tokens` jumps to roughly the whole prompt. On a healthy turn it is the other way round: reads cover the previous request and writes cover only the newest exchange.\n\nThe [prompt caching docs](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) add a third field, `input_tokens`, which counts only what comes after the last cache breakpoint. [Claude Code](https://stackness.dev/tools/claude-code)'s [caching page](https://code.claude.com/docs/en/prompt-caching) gives the rule of thumb: \"If creation stays high turn after turn, something is changing in your prefix.\" Its status line counts a miss when a request re-processed \"more than 5% and at least 2,000 tokens\" it could have read, and counts compaction separately, as an expected rebuild.\n\n## What does a prompt cache miss cost?\n\nA prompt cache miss costs the write price on the whole prefix: 1.25 times the base input price with the five-minute lifetime, 2 times with the one-hour lifetime. A hit costs 0.05 times base on Sonnet 5.5 and Opus 5.5, and 0.1 times on Haiku 5.5. So a miss on those two models costs 25 to 40 times a hit, and more than not caching at all.\n\nPrices are from Anthropic's [pricing page](https://platform.claude.com/docs/en/about-claude/pricing) on 19 October 2026, for the prefix alone on one request:\n\n| Prefix | Model | Hit | Uncached | Miss, 5-minute write | Miss, 1-hour write | \n|---|---|---|---|---|---|\n| 50k tokens | Sonnet 5.5 | $0.005 | $0.10 | $0.125 | $0.20 | \n| 100k tokens | Sonnet 5.5 | $0.01 | $0.20 | $0.25 | $0.40 | \n| 100k tokens | Opus 5.5 | $0.02 | $0.40 | $0.50 | $0.80 | \n| 50k tokens | Haiku 5.5 | $0.0005 | $0.005 | $0.00625 | $0.01 | \n\nOne miss is cents. A session that misses on every turn is not. Rajesh Beri [modelled](https://www.beri.net/article/prompt-caching-savings-cost-per-provider-hit-rate-agent-loop-2026) a 30-turn agent loop with a 20k-token prefix that grows by 1,500 tokens a turn. I recomputed it at today's Sonnet 5.5 prices with five-minute writes: $2.72 uncached, $0.41 cached, an 85% saving. Put a timestamp in the system prompt, so only the tool block is ever read back, and the session costs $2.53, a 7% saving. Change a tool description every turn and it costs $3.36, 24% more than not caching.\n\n## Sonnet 5.5's cache read cut made each miss relatively dearer\n\nAnthropic lowered Sonnet 5.5 cache reads from $0.20 to $0.10 per million tokens on 7 October 2026, and its [release notes](https://platform.claude.com/docs/en/release-notes/overview) say \"Cache writes and all other prices are unchanged.\" A miss costs the same dollars as before; a hit costs half. The ratio between them doubled, from 12.5 to 25 with five-minute writes, so a stable prefix is worth more than it was.\n\nAnthropic [said](https://x.com/claudeai/status/2107894060229034197) the cut makes Sonnet 5.5 \"around 20% cheaper to run on most long-running work\", without a published method. Opus 5.5 has charged 0.05 times base since it launched on 22 September; Haiku 5.5 stays at 0.1 times. Claude Code's `/cost`, status line and `--max-budget-usd` kept pricing Sonnet 5.5 reads at $0.20 until version 2.1.296 on 9 October, as [MIXED News](https://mixed-news.com/en/anthropic-sonnet-5-5-cache-reads-halved-claude-code-2-1-296-cost/) reported: a display error, not a billing one. The [Sonnet and Opus comparison](https://stackness.dev/blog/sonnet-5-5-vs-opus-5-5-which-slot-each-one-takes-in-a-coding-agent-stack) has the full price table, and the [language models developers pick for their agents](https://stackness.dev/categories/llms) are listed by category.\n\n## A pause longer than the cache lifetime is the first cause to rule out\n\nCache expiry is the first cause to rule out because it needs no mistake: step away longer than the lifetime and the next message re-writes the whole context, as Claude Code's [costs page](https://code.claude.com/docs/en/costs) says. The main conversation gets a one-hour lifetime on a subscription within plan usage, and five minutes on an API key, usage credits or a cloud provider. Subagents and compaction get five minutes.\n\nEach hit refreshes the lifetime for free. Boris Cherny of the Claude Code team [described](https://news.ycombinator.com/item?id=47880089) the worst case in April: 900k tokens in context, an hour idle, then one message, is \">900k tokens written to cache all at once\". A subscriber who runs into usage credits drops to five minutes mid-session, which looks like a bill that jumped for no reason.\n\n**Test:** `/usage` shows the main conversation's cache as warm or cold and when it was last active; the status line's `last_miss_cause` reports `ttl_expired_5m`. Through the API, [cache diagnostics](https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics) return no change reason while reads drop, or `previous_message_not_found` once the gap outlasts their short retention.\n\n**Fix:** set `promptCacheTtl: \"1h\"` (or `CLAUDE_CODE_PROMPT_CACHE_TTL=1h`) when your gaps run 5 to 60 minutes, and `/clear` rather than resume a large stale session. Since 2.1.299 Claude Code compacts a conversation of 200k tokens or more that has sat idle for about 54 minutes, before the one-hour cache expires.\n\n## Compaction rebuilds the conversation layer by design\n\nCompaction is an expected rebuild, not a bug. Claude Code's caching page says of compaction: \"By design, this invalidates the conversation layer\": the system prompt and tools are reused, CLAUDE.md is reloaded from disk, and the summarised history is written fresh. With a warm cache, `/compact` \"costs a fraction of what the context size suggests\"; with a cold one it re-processes the full history as uncached input.\n\nEach later turn re-reads a much smaller prefix, so a long session usually comes out ahead. Thariq Shihipar of Anthropic [wrote](https://claude.com/blog/lessons-from-building-claude-code-prompt-caching-is-everything) that Claude Code forks the compaction call with the same system prompt, tools and history so the summary request itself reads the cache. The [compaction explainer](https://stackness.dev/blog/what-is-context-compaction-in-coding-agents-and-what-does-it-quietly-lose) covers what the summary drops.\n\n**Test:** `/usage` counts compactions as expected rebuilds; OpenTelemetry emits a `claude_code.compaction` event with tokens before and after.\n\n**Fix:** compact at task boundaries while the cache is warm. `/clear` costs nothing, and `/rewind` returns to a prefix that is already cached.\n\n## Switching the model or the effort setting starts over\n\nEvery model has its own cache, so switching models mid-session re-writes everything, including through `opusplan` or a skill whose frontmatter names another model. Thariq's example: 100k tokens into an Opus session, switching to Haiku \"would actually be more expensive\" than staying. Effort and thinking settings are rendered into the prompt too, though Claude Code keeps the cache across effort changes on Opus 5.5, Sonnet 5.5, Haiku 5.5 and Fable 5.1 with an API key or a Claude subscription, not on Bedrock, Google Cloud or a Claude apps gateway. Turning on fast mode costs one miss per conversation.\n\n**Test:** diagnostics report `model_changed`, or `unavailable` for thinking and effort changes. Claude Code asks for confirmation before a model switch while the cache is warm.\n\n**Fix:** pick the model at the start, and give cheap work to a subagent instead of switching the main conversation.\n\n## A changed tool list invalidates everything after it\n\nTool definitions sit at the very top of the prompt, so any change to them invalidates everything after: system prompt and messages. In Neuralwatt's production traffic, turns where the number of tools changed broke the cache 67% of the time, against 2.8% when nothing visible changed. Tool changes happened on about 0.5% of turns and caused 19% of the re-read tokens, though three accounts made up about two thirds of that share.\n\n*Figure from [Why harnesses matter for energy efficiency](https://neuralwatt.com/news/why-harnesses-matter-for-energy-efficiency) by Chad Gibson, Neuralwatt, 2026. Measured on Neuralwatt's cloud for open models, 6-13 October 2026, turns of 8k+ tokens, top three accounts excluded.*\n\nNeuralwatt measured open models on its own cloud, not Anthropic's, and frames the cost as energy: \"A cache miss roughly doubles a request's energy.\" The mechanism is the same everywhere. In Claude Code, connecting an MCP server mid-session or toggling a plugin that ships one breaks the cache, but only when tools load upfront. With tool search on, the default, Claude Code \"keeps the tool list from the conversation's first request for the whole conversation\".\n\n**Test:** diagnostics report `tools_changed`; Claude Code's `last_miss_cause` reports `tools_changed` with counts of the tools added and removed.\n\n**Fix:** keep tool search on, change MCP servers between sessions, and in your own harness serialise tools and schema keys in a fixed order. Anthropic's docs warn that some languages, Go and Swift among them, randomise key order when converting to JSON, which breaks the cache when it reorders the keys in `tool_use` blocks; diagnostics flag a non-deterministically serialised `input_schema` as `tools_changed`.\n\n## A timestamp or a git status in the system prompt wipes out the saving\n\nAny value that changes per request in the system prompt invalidates the system block and every message after it. Timestamps, request IDs, the current date and git status are the usual culprits. Claude Code moved the date out of its own system prompt in version 2.1.42 in February 2026. Neuralwatt's lab found OpenCode 1.x and Kilo Code putting the date about 2,000 tokens in, so crossing midnight forced a near-full re-read.\n\n**Test:** diagnostics report `system_changed`, which the docs gloss as \"Typically a timestamp, request ID, or other per-request value\". In Claude Code, `last_miss_cause` reports `system_prompt_changed`. `OTEL_LOG_RAW_API_BODIES=file:<dir>` writes full request bodies you can diff (`=1` truncates them at 60 KB).\n\n**Fix:** keep the system prompt byte-for-byte stable and append dynamic values after the last breakpoint, or as a system message later in the conversation.\n\n## Edits to earlier turns break everything after the edit\n\nThe message history is cached as an append-only log, so a harness that rewrites an earlier turn misses from that point on. Memory plugins, pruning of old tool results and some [context compression tools](https://stackness.dev/blog/agent-context-compression-tools-headroom-rtk-engram-attic-compared) do this. Neuralwatt's CEO said on Hacker News that when debugging low cache rates with users, \"probably culprit #1 is usually some memory system\". In its lab, one harness replacing an earlier file read re-read 5,846 of 15,520 tokens.\n\nEditing `CLAUDE.md` mid-session is not a cause: Claude Code reads it once at start, so the edit \"does not invalidate the cache, but the edit also doesn't apply\" until `/clear`, `/compact` or a restart.\n\n**Test:** diagnostics report `messages_changed`.\n\n**Fix:** treat history as append-only, echo tool results back unchanged, and add new facts as appended reminders.\n\n## How do you measure prompt cache hit rate per session?\n\nClaude Code reports cache hit rate per session in `/usage` since version 2.1.251. A line reads like \"Prompt cache (main): 14 requests · 91% of input tokens from cache · 2 misses\", with the tokens re-cached and the TTL. It covers the main conversation only, not subagents, and its dollar figure is a local estimate.\n\nFour other routes give the same numbers:\n\n- **Status line:** a`prompt_cache` object with`hit_ratio` ,`misses` ,`expected_rebuilds` and`last_miss_cause` ([status line docs](https://code.claude.com/docs/en/statusline) ).\n- **OpenTelemetry:**`claude_code.token.usage` with`type` set to`cacheRead` or`cacheCreation` , and per-request`cache_read_tokens` and`cache_creation_tokens` on the`claude_code.api_request` event ([monitoring](https://code.claude.com/docs/en/monitoring-usage) ).\n- **Transcripts:** every assistant line in`~/.claude/projects/<project>/<session>.jsonl` carries both usage fields.[ccusage](https://stackness.dev/tools/ccusage) reads them and`ccusage session` groups them by session.\n- **The API:** send`\"diagnostics\": {\"previous_message_id\": ...}` with each request and read`cache_miss_reason` .\n\nWhat counts as good is not standardised. Across Neuralwatt's clients, uncached input ran from 1.6% to 11.1% of the total, and its post notes that 92% cached against 97% cached is \"about 2.7 times the prefill work\".\n\n## The cached prefix holds the system prompt, the tools and your CLAUDE.md\n\nThe cached prefix in Claude Code has three layers: the system prompt and tool definitions, then project context (CLAUDE.md files, auto memory and unscoped rules), then the conversation. Skills add a one-line description each until invoked, and MCP tools only their names while tool search defers them. `/context` shows the real sizes. Size changes what a miss costs, not how often one happens: the costs page advises keeping CLAUDE.md \"under 200 lines\", which saves money on every miss and does nothing for the hit rate.\n\n## If you see this, check that, fix it this way\n\n| You see | Check | Fix | \n|---|---|---|\n| A big write on the first message after a break | `/usage` cache state,`ttl_expired_5m` | `promptCacheTtl: \"1h\"` ;`/clear` instead of resuming | \n| One big write after `/compact` or auto-compact | `/usage` expected rebuilds | Compact at task boundaries while warm | \n| Writes after `/model` ,`opusplan` or a skill | `model_changed` | Pick the model at start; use subagents | \n| Writes after connecting an MCP server or plugin | `tools_changed` , tools added and removed | Keep tool search on; change servers between sessions | \n| Writes on every turn in your own harness | `system_changed` or`tools_changed` | Stable system prompt; sorted tools and keys | \n| Writes from one turn onward after a memory or pruning step | `messages_changed` | Append-only history | \n| A shorter TTL than expected on a subscription | Whether usage credits kicked in | Expect five minutes on credits | \n\n## New posts by email\n\nAbout one email a week with what we published. No account needed.\n\n## Which of these do you use?\n\nNobody on Stackness runs ccusage yet. Tick what you use and be the first.\n\n[Play Lonny Eagle Amateur Skater 4A pixel art skateboarding game. Signing up opens it straight away.Sign up to play](https://stackness.dev/games/lonny-eagle)", "url": "https://wpnews.pro/news/coding-agent-prompt-cache-miss-cost-what-breaks-the-prefix-and-how-to-find-it", "canonical_source": "https://stackness.dev/blog/coding-agent-prompt-cache-miss-cost-what-breaks-the-prefix", "published_at": "2026-10-19 08:02:18+00:00", "updated_at": "2026-10-19 09:17:09.030932+00:00", "lang": "en", "topics": ["ai-tools", "large-language-models", "ai-infrastructure", "mlops"], "entities": ["Anthropic", "Claude Sonnet 5.5", "Claude Opus 5.5", "Claude Haiku 5.5", "Claude Code", "Rajesh Beri"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/coding-agent-prompt-cache-miss-cost-what-breaks-the-prefix-and-how-to-find-it", "markdown": "https://wpnews.pro/news/coding-agent-prompt-cache-miss-cost-what-breaks-the-prefix-and-how-to-find-it.md", "text": "https://wpnews.pro/news/coding-agent-prompt-cache-miss-cost-what-breaks-the-prefix-and-how-to-find-it.txt", "jsonld": "https://wpnews.pro/news/coding-agent-prompt-cache-miss-cost-what-breaks-the-prefix-and-how-to-find-it.jsonld"}}