Short answers to what readers ask most about this topic.
01Why does switching models mid-session make Claude Code slow?
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.
02What are promptCacheTtl and subagentPromptCacheTtl?
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.
03Why do my Claude Code subagents get a five-minute cache?
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.
04Does editing CLAUDE.md mid-session invalidate the cache?
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.
05Is rewinding cheaper than compacting in Claude Code?
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.
Claude Code Prompt Caching: Tune the TTL, Cut the Bill
Caching matches the request prefix exactly, so switching model mid-task re-reads everything. Here are the two TTL buckets and the invalidations worth avoiding.
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.
One prefix, matched exactly, with no per-file caching
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.
The things that invalidate, including two that are not text
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:
Switching model, or changing effort level. Neither is part of the prompt text, but both are part of the cache key, so each has its own cache for the same content.
Turning on fast mode, which adds a request header that is part of the cache key. The cost applies once per conversation, so enabling it at the start of a session costs far less than deep into a long one.
Connecting or disconnecting an MCP server whose tools are loaded into the prefix rather than deferred — which can happen with no action from you when a stdio process exits or an HTTP session expires.
Adding a bare tool name as a deny rule, which removes that tool from context entirely and changes the system prompt layer.
Upgrading Claude Code, since a new version typically changes the system prompt or tool definitions.
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.
The things that are safe, and why some settings wait for a restart
This list is the more useful one, because several of these look like they should cost something and do not:
Editing files in your repository. File contents enter context only when Claude reads them, and a later edit appends a system reminder rather than rewriting the earlier read.
Editing CLAUDE.md mid-session. It does not invalidate the cache — but the edit also does not apply, because the file was read once at session start and held in memory.
Changing output style, for the same reason. Both load on the next clear, compact or restart.
Changing permission mode, invoking a skill or command, and running the recap command, all of which append rather than rewrite.
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.
Two buckets, and the one that catches people out
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.
Scope: one machine, one directory
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.
Measuring it, so you stop guessing
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.
The three habits that actually moved my numbers
Everything above reduces to a short list:
Pick the model and effort level at the top of a session, not in the middle of one. Both are cache keys, and a mid-task switch costs a full re-read of everything so far.
Compact at a natural break between tasks rather than letting auto-compaction fire mid-task, and rewind instead of compacting when you are abandoning a path rather than finishing one.
Set the subagent TTL to an hour before any long multi-agent run, and leave it at the default the rest of the time. The higher write rate only pays for itself when there are real gaps between turns.
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.