Claude Code Prompt Caching: Tune the TTL, Cut the Bill

Each model has its own prompt cache. Switching means the next request reads the entire conversation history with no cache hits, even though the content is identical. Effort level works the same way — each level has its own cache for the same model — so both are worth choosing at the top of a session rather than in the middle of one.
They set the cache time-to-live for the two request buckets. promptCacheTtl covers the main conversation; subagentPromptCacheTtl covers subagents, workflows, in-process teammates, forks, compaction and session titles. Each accepts only 5m or 1h, and both require Claude Code v2.1.242 or later.
Subagents fall outside the main-conversation TTL bucket, so they get five minutes by default even on a Claude subscription where the main conversation gets an hour. Set subagentPromptCacheTtl to 1h before a long multi-agent run; the API bills one-hour cache writes at a higher rate, so it only pays off when there are real gaps between turns.
No, but the edit also does not apply. Project-root and user-level CLAUDE.md files are read once at session start and held in memory, so Claude keeps working with the version loaded then. The new content loads on the next /clear, /compact or restart. Output style behaves the same way.
Usually, yes. Rewinding truncates the conversation back to an earlier turn, and that remaining history is exactly what the cache was built from, so the next request hits the existing cache entry. Compaction replaces your history with a summary, which is a new prefix that has to be cached from scratch.

Key Takeaway
Claude Code caches by matching the exact start of each request, so a change anywhere in the prefix recomputes everything after it. Model and effort level are part of the cache key without appearing in the prompt text. Two TTL buckets exist — the main conversation and everything else — controlled by promptCacheTtl and subagentPromptCacheTtl, each accepting only 5m or 1h.
I switched from Sonnet to Opus about ninety minutes into a long session because the problem had got harder. The next turn took noticeably longer and cost more than any turn before it, and I spent ten minutes convinced the model was slow. It was not. Every model has its own cache, and I had just thrown away ninety minutes of cached prefix for free.
Prompt caching is handled for you and mostly invisible, which is exactly why the moments it costs you are confusing. This post covers how the prefix actually works, the two cache-key inputs that are not in the prompt at all, which actions invalidate and which are safe, the two TTL buckets and how to choose them, and how to measure whether any of it is working.
The model remembers nothing between requests, so Claude Code re-sends everything every turn: system prompt, project context, every prior message and tool result, then your new message. Caching is how the API avoids reprocessing the part that did not change. It matches the start of the request — the prefix — against content it recently processed, and the match is exact.
# Claude Code orders every request so the rarely-changing
# content comes first. The API matches the PREFIX exactly, so a
# change anywhere recomputes everything after it.
1. System prompt <- tool definitions, output style
changes on upgrade, or when the tool set changes
2. Project context <- CLAUDE.md, auto memory, unscoped rules
changes at session start, /clear or /compact
3. Conversation <- your messages, replies, tool results
changes every turn
# There is NO per-file or per-segment caching. A change in
# layer 1 invalidates 2 and 3 behind it.
#
# Two more things are part of the cache key without being in
# the prompt text at all:
# - the MODEL (each model has its own cache)
# - the EFFORT LEVEL (each level has its own cache per model)The consequence people miss is that there is no per-file or per-segment caching. Nothing is cached individually. A change in the system prompt layer invalidates the project context and the entire conversation behind it, because all of that now sits after a different prefix. This is also why plan mode and skill loading are cheap: both append their instructions as conversation messages rather than editing anything earlier.
Each of these causes one slower, more expensive turn, after which the new prefix is cached. Most are avoidable mid-task once you know they cost something:
Resuming a session after an upgrade reprocesses the entire conversation history with no cache hits, because the history now sits behind a different system prompt. The cost scales with how long that conversation is, so the first turn back into a long resumed session can be the single most expensive request you send. Auto-update never applies mid-session, which is why this shows up as a slow first turn rather than a surprise.
This list is the more useful one, because several of these look like they should cost something and do not:
Rewinding is the interesting one. It truncates the conversation back to an earlier turn, and the remaining history is exactly the content the cache was built from at that point, so the next request hits the earlier cache entry. Every turn since then read through that prefix, which kept it warm. If you have gone down a path you want to abandon entirely, rewinding is cheaper than compacting — compaction builds a new prefix, rewinding returns to one that already exists.
Claude Code decides the TTL per request, and every request falls into one of two fixed buckets. The API offers a five-minute TTL and a one-hour TTL that survives longer breaks but bills cache writes at a higher rate.
What each bucket gets by default:
| Request bucket | Claude subscription, within plan usage | Usage credits, API key, or cloud provider |
|---|---|---|
| Main conversation | One hour | Five minutes |
| Everything else | Five minutes, apart from server-controlled helpers | Five minutes |
// Two controls, one per bucket. Each takes exactly 5m or 1h;
// any other value is ignored. Both need v2.1.242 or later.
{
"promptCacheTtl": "1h", // main conversation
"subagentPromptCacheTtl": "1h" // subagents, workflows, teammates,
// forks, compaction, session titles
}
# Precedence, first match wins:
#
# 1. FORCE_PROMPT_CACHING_5M=1 forces 5m on BOTH buckets
# 2. the bucket's env var CLAUDE_CODE_PROMPT_CACHE_TTL
# CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL
# 3. the bucket's setting the JSON above
# 4. ENABLE_PROMPT_CACHING_1H=1 requests 1h on BOTH buckets
# 5. the default for that bucket
#
# Use FORCE_PROMPT_CACHING_5M=1 to override a longer TTL that
# managed settings imposed, or while measuring the difference.The second row is the one that catches people out. Subagents, workflows, in-process teammates, forks, compaction and session titles all fall outside the main conversation, so they get five minutes even on a subscription. On a multi-agent run with long gaps between turns, that is the difference between reading a cached prefix and reprocessing it — set the subagent TTL to an hour before a long fan-out, and accept the higher write rate.
In Claude Code the cache is effectively scoped to a machine and a directory. The system prompt embeds the working directory, platform, shell, OS version and auto-memory paths, so two sessions in different directories build different prefixes and miss each other entirely. That includes worktrees of the same repository, since each worktree has its own working directory — which is a real cost of the parallel-worktree pattern that nobody mentions when recommending it.
Sessions running in parallel in the same directory do build matching prefixes and read each other's cache. Sequential sessions share it only when the git status snapshot at startup matches, because the system prompt also captures branch and recent commits. The underlying API cache is broader — isolated between organisations, and on some providers between workspaces — so any two requests with the same model and prefix inside those boundaries read the same cache.
Two token counts on every API response tell you whether any of the above is working. Watch the ratio rather than the absolute numbers: a high read-to-creation ratio means caching is doing its job, and creation staying high turn after turn means something in your prefix is moving.
# The API reports two counts on every response. A statusline
# script reading current_usage is the cheapest way to watch them.
cache_creation_input_tokens # written this turn, billed at the WRITE rate
cache_read_input_tokens # served from cache, ~10% of standard input
# A high read-to-creation ratio means caching is working.
# Creation staying high turn after turn means something in your
# prefix is moving — start with the tool layer.
# Across a team, the OpenTelemetry exporter reports both per
# user and per session, so you can find the one developer whose
# gateway silently stripped the cache markers.Where the cache lives depends on how you authenticate, and this is where gateway setups go quiet. Claude Code keeps the conversation's own cache breakpoints in place, so a gateway that forwards them still caches your conversation — but before v2.1.237, a gateway that silently removed the marker on the mid-conversation system block left the entire conversation billed as uncached input on every turn. If you are behind a gateway and your numbers look wrong, check the version before you check the gateway.
Everything above reduces to a short list:
The reason to learn any of this is not the bill, it is the diagnosis. Once you know that caching is a single exact prefix match and that model and effort sit in the key, an unexplained slow turn stops being mysterious — it is almost always something you changed, and the list of things that can change it is short. Everything else about the session can stay as complicated as it needs to be.
Sources & further reading