Claude Code re-sends your entire conversation history on every turn: the system prompt, your project context, every prior message and tool result, plus whatever you just typed. Prompt caching is what stops that from being reprocessed in full each time, and as of Claude Code v2.1.242 (25 August 2026), two settings let you choose exactly how long that cache stays warm: promptCacheTtl and subagentPromptCacheTtl. Both are documented in Claude Code's settings reference and its dedicated prompt caching page, and they're worth understanding even if you never touch either one, because the default you get depends on how you're signed in.
How prompt caching actually works in Claude Code
Every request Claude Code sends is layered so the parts least likely to change come first: the system prompt, then project context like CLAUDE.md, then the conversation itself. The API matches the start of a new request, the prefix, against content it recently processed. When the match holds, that portion is billed at a fraction of the standard input rate instead of being reprocessed from scratch.
That caching only helps if the cached entry is still there when you send the next request. Caches expire after a period of inactivity, and the length of that window, the time to live, is the whole subject of these two settings.
Two fixed TTLs, not a sliding scale
The underlying Claude API offers exactly two cache lifetimes: a five-minute TTL, and a one-hour TTL that survives a longer break at a higher cache-write rate. Claude Code doesn't expose anything in between. Every request it sends falls into one of two buckets, and each bucket gets its own TTL:
| Request bucket | What's in it |
|---|---|
| Main conversation | Your interactive turns, non-interactive -p runs, Agent SDK turns, and the helper requests Claude Code runs inline with them |
| Everything else | Subagents, workflows, agent teams, forks, compaction, and session titles |
promptCacheTtl controls the first bucket. subagentPromptCacheTtl controls the second. They're separate settings because Claude Code doesn't default them the same way.
Which TTL you get by default
Unless you choose one yourself, the default depends on how your session authenticates and whether you're still within your plan's included usage:
| Request bucket | Claude subscription, within plan usage | Usage credits, API key, or cloud provider |
|---|---|---|
| Main conversation | One hour | Five minutes |
| Everything else | Five minutes (server-controlled helper requests get one hour) | Five minutes |
The pattern worth noticing: only a Claude subscription's main conversation gets the longer TTL automatically, and only while you're inside your plan's included usage. The moment you draw on usage credits because you've gone over your plan's limit, Claude Code drops the main conversation back to five minutes, because you're now being billed for that usage and the higher cache-write rate isn't something it applies without you asking for it. Subagents, workflows and the rest of the "everything else" bucket default to five minutes regardless of how you're signed in, with one carve-out: a small set of server-controlled helper requests that Anthropic manages get the hour automatically even there.
If you sign in with an API key or run on a cloud provider like Amazon Bedrock, Google Cloud's Agent Platform or Microsoft Foundry, you get the five-minute default everywhere, full stop, unless you set the TTL yourself.
Where the cache actually lives
Caching happens server-side, and where "server-side" means depends on how a session authenticates:
- API key, Claude subscription, or Claude Platform on AWS: the cache lives in Anthropic's own infrastructure, accessed through the Claude API.
- Amazon Bedrock or Google Cloud's Agent Platform: the cache lives in your cloud provider's own serving infrastructure instead.
- Microsoft Foundry: depends on the deployment's hosting option. A deployment hosted on Azure is served, and cached, on Azure infrastructure; one hosted on Anthropic is cached on Anthropic's own infrastructure.
- A custom
ANTHROPIC_BASE_URLor an LLM gateway: the cache lives wherever your requests are actually forwarded to, and whether caching works at all from there depends entirely on that gateway.
This matters because the one-hour TTL isn't universally available. It isn't offered through the Claude apps gateway at all. On Amazon Bedrock specifically, prompt caching support, the minimum cacheable prefix length, and whether the one-hour TTL is even available vary by model and region, so setting promptCacheTtl: "1h" there doesn't guarantee you actually get the longer lifetime; if cache token counts stay stubbornly at zero regardless of the setting, that's the first thing to check against Bedrock's own supported-models list rather than assuming the setting itself is broken.
Setting it yourself
Both settings take exactly two values, "5m" or "1h". Anything else is ignored. Add them to any settings file:
{
"promptCacheTtl": "1h",
"subagentPromptCacheTtl": "1h"
}
Or set the equivalent environment variables, which take effect at startup:
export CLAUDE_CODE_PROMPT_CACHE_TTL="1h"
export CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL="1h"
Both require Claude Code v2.1.242 or later. If you authenticate with an API key or a cloud provider and want the longer main-conversation cache, promptCacheTtl: "1h" is the setting that gets it for you; nothing else changes that default on its own.
Precedence when more than one control applies
Claude Code checks these in order and stops at the first match:
FORCE_PROMPT_CACHING_5M=1forces five minutes for both buckets, overriding everything else- The bucket's environment variable (
CLAUDE_CODE_PROMPT_CACHE_TTLorCLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL) - The bucket's setting (
promptCacheTtlorsubagentPromptCacheTtl) ENABLE_PROMPT_CACHING_1H=1requests one hour for both buckets- The bucket's default from the table above
FORCE_PROMPT_CACHING_5M=1 is specifically useful for debugging cache behaviour or overriding a longer TTL an organisation has set in managed settings, since it wins regardless of what else is configured.
Why the choice actually matters
The one-hour TTL earns its higher write rate when you step away from a session and come back later: without it, the first request after a long break reprocesses your entire history as uncached input, which is slower and more expensive than a cache hit would have been. That's a real cost on a session you leave open across a lunch break, a long build, or an overnight run.
The same TTL is a net loss on short, continuous bursts of work. If you never leave a five-minute gap, the one-hour cache's longer lifetime goes completely unused, and you've paid its higher write rate for nothing. Pick the TTL based on your actual working pattern, not a blanket preference for "longer is safer."
Subagents deserve a specific mention here. A subagent starts its own conversation with its own system prompt, so its first request never reads the parent's cache; it warms a cache of its own across its own turns. Subagents fall into the "everything else" bucket regardless of what the main conversation's TTL is set to, so a long-running fleet of subagents, the kind a workflow fans out, benefits from subagentPromptCacheTtl: "1h" independently of whatever you've set for the main conversation.
Checking whether it's working
Cache performance shows up as two fields on every API response: cache_creation_input_tokens, tokens written to the cache this turn at the cache-write rate, and cache_read_input_tokens, tokens served from cache at roughly 10% of the standard input rate. A statusline script that reads the current_usage object is the most direct way to watch these live. A high read-to-creation ratio means caching is doing its job. If creation stays high turn after turn, something in your prefix keeps changing, model switches, effort-level changes, MCP servers connecting or disconnecting mid-session, and enabling a longer TTL won't fix that on its own.
What still invalidates the cache regardless of TTL
A longer TTL only helps the cache survive a gap in time. It does nothing about the actions that invalidate a cache entry outright, and Claude Code's own documentation lists the same set whatever TTL you've chosen:
- Switching models with
/model, including anopusplantoggle between plan mode and execution - Changing effort level with
/effort - Turning on fast mode
- A tool set change from an MCP server connecting or disconnecting, when its tools are loaded into the prefix rather than deferred
- Enabling or disabling a plugin that provides MCP servers loaded into the prefix
- Adding or removing a bare-tool-name deny rule (
Bash,WebFetch, or a wildcard like"*") - Compacting the conversation with
/compact - Upgrading Claude Code itself
None of these are TTL problems. They're prefix-shape problems: the cached entry no longer matches what the next request would send, so the API has nothing to hit regardless of how long ago you last sent a message. If you're seeing a slow, expensive turn right after one of these actions, that's expected, and a longer TTL wouldn't have prevented it.
Where this fits with other cost controls
promptCacheTtl and subagentPromptCacheTtl sit alongside a growing set of Claude Code settings for managing spend on a fleet or a team, including modelPricing for an organisation's contracted per-model rates and the ANTHROPIC_DEFAULT_MODEL environment variable for pinning which model new sessions start on. None of them substitute for the others: pinning a model controls what you're billed for per token, modelPricing controls the rate that billing uses, and the cache TTL settings control how much of each request has to be reprocessed at all. On a team running many sessions per day, especially through an Agent SDK integration or a fleet of self-hosted runners, the cache TTL is usually the highest-leverage of the three, because reprocessing cost scales with how much history a session has accumulated by the time it goes cold.
Troubleshooting
Setting promptCacheTtl had no visible effect. Confirm you're on Claude Code v2.1.242 or later; the setting is silently unavailable on earlier versions. Also check whether an environment variable or a managed setting is overriding it, using the precedence order above, since the setting is only step 3 of 5.
Cache reads stay at zero no matter what TTL is set. This usually isn't a TTL issue at all. Check whether your provider disables caching for your setup, a custom ANTHROPIC_BASE_URL, an LLM gateway that strips cache breakpoints, or an Amazon Bedrock model or region that doesn't support the one-hour TTL. The cache lifetime setting can't create caching support a given path doesn't have.
A value other than "5m" or "1h" doesn't do what you expected. Claude Code silently ignores any value outside that pair rather than erroring, so a typo like "1hr" behaves as if the setting were never set at all. Double-check the exact string.
Where to go next
Claude Code's own prompt caching page is the full reference this article draws from, including the complete list of actions that keep versus invalidate the cache. For the model side of session cost, see ANTHROPIC_DEFAULT_MODEL: setting Claude Code's default model per machine. For a related settings-only control that doesn't touch a skill's own file, see Claude Code's skillOverrides setting explained. Browse the full skill catalogue at getclaudeskills.com/platforms/claude-code.
Verified 26 August 2026 directly against Claude Code's prompt caching and settings reference documentation at code.claude.com, both read in full, following the promptCacheTtl and subagentPromptCacheTtl settings introduced in v2.1.242 (25 August 2026).
