Your 5-minute cache doesn’t last 5 minutes: what promptCacheTtl actually fixes
Claude Code 2.1.243 shipped the setting a user requested on May 18. Whether it saves you money or not depends on a number the changelog doesn’t mention.
On August 25, 2026, the Claude Code changelog brought this line:
“Added
promptCacheTtlandsubagentPromptCacheTtlsettings so API-key and cloud-provider users can keep a 1-hour prompt cache on the main conversation while subagents stay at 5 minutes”
Two settings, one line each in settings.json. The temptation is to paste "promptCacheTtl": "1h" and move on — and for a good chunk of readers that would either be redundant or a small, silent price increase.
The clause that decides which of the two cases you are is exactly the one most coverage cuts: API-key and cloud-provider users. Before you get to the configuration, you need to understand three things: who already had this by default, how much the hour actually costs, and why five minutes in Claude Code isn’t five minutes.
If per-token billing mechanics aren’t familiar to you, What are tokens in AI and why do they charge you for them explains the foundation everything that follows rests on: why you pay for the entire conversation each turn, and why the cache is the lever that exists to avoid paying for it twice.
First: check if you already have it
The prompt caching documentation publishes the default TTL for each request Claude Code makes, divided into two buckets. The main conversation is your interactive turns, runs with -p, and Agent SDK turns. Everything else is subagents, workflows, teammates in-process, forks, compaction, and session titles — a bucket much broader than the word “subagents” suggests.
| Request bucket | Claude subscription, within included usage | Usage credits, API key, or cloud provider |
|---|---|---|
| Main conversation | One hour | Five minutes |
| Everything else | Five minutes (except helper requests the server controls, which get one hour) | Five minutes |
Read the left column again. On a Pro, Max, Team, or Enterprise plan, within your included usage, the main conversation is already on a one-hour cache and subagents are already at five minutes. The exact fix the changelog describes is your current default. Putting promptCacheTtl to 1h there changes nothing.
The setting does matter if you’re in any of these situations:
- You log in with an API key.
- You run on Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry.
- You’re on a subscription and went over your plan’s limit into usage credits. This is the case that gets overlooked: once Claude Code starts consuming credits, you’re billed per token, so the main conversation drops to a five-minute TTL on its own. If you want to get the hour back while spending credits, now you have to ask for it.
Two availability caveats before you plan with this: the one-hour TTL isn’t available through the Claude apps gateway, and on Amazon Bedrock, caching support, the minimum length of the cacheable prefix, and the availability of the hour vary by model.
Second: the hour isn’t free
This is where “measurable token savings” needs a correction. The one-hour cache is a different pricing tier, not an optimization. According to Claude’s API pricing rules:
- Cache read: 0.1× base input price
- Cache write, 5-minute TTL: 1.25× base input price
- Cache write, 1-hour TTL: 2× base input price
So you pay a 60% premium on each cache write in exchange for a window twelve times as long. The Claude Code documentation is direct about the case where it goes wrong: the hour “costs more on short bursts of work that never idle past five minutes, where the higher write rate applies and the longer cache lifetime goes unused” — costs more on short work bursts that never sit idle longer than five minutes, where the higher write rate applies and the longer lifetime doesn’t get used.
Do the math on a 200k-token context at Sonnet 5 list pricing, US$2 per million input tokens:
| Operation | Rate | Cost per 200k tokens |
|---|---|---|
| Cache read (hit) | $0.20 / Mtok | $0.04 |
| Cache write, 5m | $2.50 / Mtok | $0.50 |
| Cache write, 1h | $4.00 / Mtok | $0.80 |
Choosing the hour costs you $0.30 extra on the write. A single cache miss you avoid — a turn that would’ve rewritten 200k tokens at $0.50 instead of reading them at $0.04 — saves you $0.46. Break-even is a single idle gap per hour. Below that you’re paying the premium for nothing; above it, the setting pays for itself and keeps paying, because the one-hour entry refreshes at no extra cost each time it’s read.
That’s the honest framing: promptCacheTtl: 1h is a bet that you get up from the terminal. If you sit two hours in unbroken flow, don’t take it.
Third: five minutes are less than you think
Here’s the detail that’s not in the changelog, not in Claude Code’s documentation, and reframes the entire setting. From the API’s prompt caching reference:
“The lifetime is measured from the start of the request that writes or reads the cache entry, not from the end of its response. Time spent generating a response counts against the lifetime: if a response takes 4 minutes to stream, a follow-up request that reuses the same cached prefix must start within about 1 minute of that response completing.”
In other words: the lifetime is measured from the start of the request that writes or reads the entry, not from the end of its response. The time it takes to generate the response counts against the lifetime — if a response takes 4 minutes to stream, the follow-up request that reuses that cached prefix has to start within about a minute of that response finishing.
Think about what a Claude Code turn really is. Extended thinking, reading a file, three edits, a test run, a summary. Agentic turns stream for minutes as a matter of course. Each of those minutes comes out of your five-minute budget — the clock started when the request went out, not when the response finished printing.
The practical upshot: with a five-minute TTL, a long agentic turn can leave you less than a minute to read the result, think, and write your next message before the entire prefix expires. That’s the mechanism behind the complaint that spawned this feature, and it explains why this same setting matters far less in a chat app, where responses take seconds.
The request that took three months
promptCacheTtl isn’t a name Anthropic invented. It’s the name a user proposed.
Issue #60316, “Expose cache_control.ttl (5m / 1h) as a user-configurable setting”, was opened on May 18, 2026 by OniLorenz-TomTom, running Claude Code 2.1.133 on Ubuntu 24.04. The request pointed to exactly two things: a settings.json key written "promptCacheTtl": "1h", or a CLI flag. The key that shipped on August 25 carries the issue’s name, character for character. The issue remains open.
The motivation section is the strongest cost evidence in this whole story, and it’s worth flagging clearly: these are numbers self-reported by a user on his own sessions, not a benchmark. He reports that when a pause between turns exceeded five minutes, his cache_create tokens jumped roughly 15× — from around 10k to around 154k — and that this happened 10 to 20 times per session on heavy thinking days, costing him roughly US$25 per day per active session on cache misses alone. His break-even calculation: above the 24% cache reuse within the hour, the one-hour tier mathematically comes out cheaper.
Take the dollar figure as a developer’s experience with a workload. Take the shape — the 15× jump, the frequency, the break-even threshold — as the reason why the setting exists.
The Configuration
Both settings accept exactly two values, 5m and 1h. Claude Code ignores anything else.
{
"promptCacheTtl": "1h",
"subagentPromptCacheTtl": "5m"
}
That’s the changelog line’s arrangement: the hour where your conversation lives, five minutes for everything that rises and falls. It goes in any settings file — ~/.claude/settings.json for all your projects, .claude/settings.json to share with your team, .claude/settings.local.json for you alone here.
There are environment variables for both buckets, which the changelog doesn’t mention:
export CLAUDE_CODE_PROMPT_CACHE_TTL=1h
export CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL=5m
And when multiple controls apply at once, Claude Code takes the first match in this order:
FORCE_PROMPT_CACHING_5M=1— forces five minutes on both buckets- The bucket’s environment variable
- The bucket’s setting
ENABLE_PROMPT_CACHING_1H=1— requests one hour for both buckets- That bucket’s default
FORCE_PROMPT_CACHING_5M=1 is the one worth remembering. The documentation recommends it for debugging cache behavior or comparing the two tiers — and, notably, for overriding a longer TTL set in managed settings. If your organization deploys the hour across the entire fleet and you want to measure what it’s doing to your own account, that’s your escape hatch.
To verify that any of this is working, look at two fields the API returns in each response: cache_creation_input_tokens and cache_read_input_tokens. A high ratio of reads to creations means caching is doing its job. If creation stays high turn after turn, there’s something in your prefix that keeps changing — and the TTL isn’t your problem.
The Other Two Settings from the Same Release, and an Honest Gap
The same changelog entry brought a breakdown of Loops in /usage: one row per /loop or heavy scheduled task, ordered by total tokens, with how often it fires, how many times it ran, tokens total and per run, and when it last ran. Rows are indexed by the task’s prompt, so a loop you stop and recreate remains a single row. If you have automation running against your account, this is the first place Claude Code will show you which task is eating the budget.
Then there’s modelPricing, described in the changelog as a managed setting that makes /cost, the status line, and telemetry use the per-model rates contracted by your organization and its discount multiplier instead of list price. For a team in Latin America paying an API bill in USD against a negotiated contract, that’s the difference between an estimate and a number you can put in a report.
We still can’t tell you how to configure it. A literal search for modelPricing returns ABSENT from the settings reference, ABSENT from the managed settings page, and ABSENT from the costs page — which also keeps documenting the old behavior, saying /usage calculates tokens “at standard list rates, so it doesn’t reflect promotional pricing or contracted discounts”. The string is present in the shipped binary. The documentation just didn’t catch up. If you’re an admin and planning around this, wait for the settings reference to publish the form instead of guessing the JSON.
One more discrepancy worth knowing, because it’ll confuse anyone checking compatibility: the changelog files all three features under 2.1.243, while the documentation for both the TTL settings and the Loops breakdown says they require v2.1.242 or later.
What to Do Concretely
Today. Run claude --version. If you’re below 2.1.243, upgrade — but don’t stop there. 2.1.245 and 2.1.246 shipped the same day, and 2.1.245 fixes a startup crash on distributions running glibc 2.44, which includes Arch, CachyOS, and Fedora Rawhide. 2.1.246 is the version to be on.
This week. Figure out which column of that defaults table you’re in. On a subscription within your included usage, you already have the fix and there’s nothing to configure — but note the moment you cross into usage credits, because then your main conversation drops to five minutes of silence. With an API key or cloud provider, set promptCacheTtl to 1h and leave subagentPromptCacheTtl as is; subagents spin up their own conversation with their own prefix and rarely live long enough to benefit from the hour.
Before you commit the setting to your team’s settings.json. Measure. Watch cache_creation_input_tokens for a few days at your normal work pace, and be honest about whether your sessions stay inactive for more than five minutes or you work in bursts without breaks. If it’s the latter, the hour is a 60% overprice in writes that doesn’t buy you anything. FORCE_PROMPT_CACHING_5M=1 gives you a clean comparison.
The setting is one line. Knowing if you want it takes a week of looking at your own numbers — which is exactly the kind of thing the Loops breakdown and modelPricing are there to make visible, once the documentation lets us use them.
Which column of that table are you in, and have you measured how many times per session your cache expires? Tell me in the comments.