OpenAI Prompt Caching: When Is the New 12-Hour Cache Cheaper?
OpenAI's 12-hour prompt cache doubles the write price of the 30-minute default. A break-even rule, five modeled workloads, and a replay script show when longer retention lowers the bill and when a higher hit rate costs more.

- Written by
- Puneet Arora (opens in a new tab)
- Published on
- Read time
- 13 min
Your prompt caching dashboard shows a healthy read hit rate. The inference bill stays high anyway. Then OpenAI ships 12-hour prompt caching, and someone on the team asks whether you should switch.
On GPT-5.6 and later, a 12-hour (12h) cache write costs 2.5x the input price, while a write at the default 30-minute (30m) lifetime costs 1.25x. So 12h only pays when the same unchanged prefix comes back after two or more gaps longer than 30 minutes inside a 12-hour window. Otherwise 30m is cheaper, even when 12h shows a higher hit rate.
Hit rate counts reads. It says nothing about what you paid to write the prefix, and that write price now depends on the retention you pick. You can price each prefix from your own request logs with one rule and about 30 lines of Python.
TL;DR
- On GPT-5.6 and later in the Responses API, you choose a 30-minute or 12-hour minimum lifetime, and the 12-hour write costs twice as much.
- Count the gaps longer than 30 minutes after which the same prefix is reused inside one 12-hour window. With zero or one, 30m is cheaper. From two, 12h is cheaper.
- A higher hit rate can come with a higher bill. In the modeled scenarios, 12h lifts the hit rate by five points and still costs more in one case, and ties on hit rate while costing 36% more in another.
- Decide from cost per prefix per window, calibrated with your own usage fields.
What changed on October 20, 2026
OpenAI's changelog entry reads: "You can now choose 12-hour prompt caching in the API. 12-hour prompt caching keeps shared instructions, tools, and context cached longer to benefit from lower cached-input pricing, even when requests are hours apart. 12-hour cache writes cost 2.5x the input token price." The entry is tagged for the Responses API, and the two model generations now follow different rules.
| Models | Setting | Values | Write charge | What the lifetime means |
|---|---|---|---|---|
| GPT-5.6 and later | prompt_cache_options.ttl (Responses API) | 30m (default) or 12h | 1.25x input for 30m, 2.5x for 12h | A minimum lifetime for read-price eligibility |
| Earlier models | prompt_cache_retention | in_memory or 24h | None | A best-effort maximum |
The prompt caching guide says the older 24h setting "typically keeps entries available for around 30 minutes and can retain them for up to 24 hours." Twenty-four hours is the ceiling. The new 12 hours is a floor: for that long, a matching prefix is eligible for the cached-input price. Since May 29, 2026, 24h has been the default for organizations without zero data retention (ZDR), with no write charge.
How OpenAI prompt caching bills a prefix
The cache stores key-value (KV) tensors for a reusable prefix, the unchanged tokens at the start of the prompt. It does not store the tokens themselves, and caching "does not change how the model generates output tokens." On GPT-5.6 and later, the minimum cacheable prompt is 1,024 tokens. Caching is on by default for supported models, and the guide documents no way to turn it off.
You control where the prefix ends. With mode set to implicit, OpenAI places a breakpoint at the end of the latest eligible message. With explicit, you place your own breakpoints, and each request can create up to four cache writes. Tokens after the last breakpoint are billed at the uncached input rate with no write charge.
Each prefix then meets three prices:
- The write: 1.25x the input rate for 30m, 2.5x for 12h.
- The read: 0.1x the input rate on most of these models, and 0.05x on
gpt-6.1-sol. - The rewrite: a full new write when a request arrives after coverage has ended.
The guide works one example: "At the 0.1× read rate with 30-minute writes, writing a prefix once and fully reusing it once costs 1.35× its ordinary input cost, compared with 2× for processing it twice without caching."
Reads also extend coverage. In the guide's words, "A 30-minute read refreshes coverage to at least 30 minutes after that read. If it uses an entry with valid 12-hour coverage, it preserves the later of the existing expiry and 30 minutes after the read. It does not restart a 12-hour clock or incur another write charge." Upgrading valid 30-minute coverage to 12 hours charges a new 12-hour write, with no credit for the earlier write.
The prefix must also stay identical. Changes to tools, text.format, reasoning.effort, and text.verbosity affect the cached prefix, so keep stable instructions and shared reference material first and variable content at the end.
The break-even rule
The guide frames the choice in one line: "Compare the higher 12-hour write rate with the cost of rewriting the prefix after 30-minute coverage expires."
With 30m, every long gap costs a fresh write at 1.25x. With 12h, you pay 2.5x once and every long gap costs only a read, so from the second long gap 12h costs less.
Write the cost of one prefix over one 12-hour window as a multiple of its ordinary input cost:
- 30m: 1.25 × (1 + G)
- 12h: 2.5 + (r × G)
The inputs:
- G (measured, from your trace): the number of gaps longer than 30 minutes after which the same unchanged prefix is reused inside one 12-hour window.
- r (from the guide and the price list): the read rate, 0.1 on most GPT-5.6 and later models or 0.05 on
gpt-6.1-sol. - 1.25 and 2.5 (from the guide): the write multipliers.
Reads inside a burst cost the same under both options, so they drop out. At G = 0, it is 1.25 against 2.5. At G = 1, it is 2.5 against 2.55 (r = 0.05) or 2.6 (r = 0.1), so 30m still wins. At G = 2, it is 3.75 against 2.6 or 2.7, so 12h wins.
A service that runs longer than 12 hours needs a new 12h write in each window, because reads do not restart the 12-hour clock. The openclaw maintainers merged 12h support the day after launch as an opt-in, with write-price accounting, in their pull request to opt into 12-hour prompt caching.
Five modeled scenarios: an illustration with list prices, not a benchmark
The numbers in this section come from a replay model run on OpenAI list prices. They are not results from production traffic, and the replay model makes no API calls. Every scenario uses these assumptions:
- Prices for
gpt-6.1-sol, Standard tier, short context, per 1M tokens, from OpenAI's pricing page: input $2.00, cached input $0.10, cache write 30m $2.50, cache write 12h $5.00, output $10.00. - One stable 20,000-token prefix (system prompt, tool definitions, reference material) with an explicit breakpoint at its end.
- 1,000 variable input tokens after the breakpoint per request, at the uncached input rate with no write charge.
- 500 output tokens per request.
- Every request inside coverage is a read.
- A read extends coverage to at least 30 minutes after it and never restarts the 12-hour clock.
- A request after coverage ends is a fresh write.
- "No cache" is a reference line only, with every prefix token at the input rate. It is not a setting OpenAI documents.
- Hit rate is the share of requests that read the prefix.
Modeled illustration with OpenAI list prices (gpt-6.1-sol, Standard tier). Not a benchmark.
| Scenario | Requests | No-cache reference | 30m cost and hit rate | 12h cost and hit rate | Cheaper option |
|---|---|---|---|---|---|
| A. Steady: one request every 2 minutes for 8 hours (G = 0) | 240 | $11.2800 | $2.2080, 239/240 (99.6%) | $2.2580, 239/240 (99.6%) | 30m, by $0.05 |
| B. Bursty: six bursts of 10 requests 30 seconds apart, bursts start 90 minutes apart (G = 5) | 60 | $2.8200 | $0.8280, 54/60 (90.0%) | $0.6380, 59/60 (98.3%) | 12h, 23% cheaper |
| C. Sparse: four requests three hours apart (G = 3) | 4 | $0.1880 | $0.2280, 0/4 (0%) | $0.1340, 3/4 (75.0%) | 12h |
| D. Same bursts as B, but the prefix changes before each burst (G = 0 for every prefix) | 60 | $2.8200 | $0.8280, 54/60 (90.0%) | $1.1280, 54/60 (90.0%) | 30m (12h costs 36% more) |
| E. Two bursts of 10 requests, two hours apart (G = 1) | 20 | $0.9400 | $0.2760, 18/20 (90.0%) | $0.2780, 19/20 (95.0%) | 30m, by $0.002 |
In every row, the cheaper option is the one the break-even rule predicts from G. In A and D the hit rates tie while the costs differ, and in E the higher hit rate belongs to the more expensive option.
In C, every 30m request is a write at 1.25x, so 30m costs more than the no-cache line. D is the deploy case: a release edits tool definitions, or a timestamp sits in the system prompt, so each burst starts with a new prefix and the 12-hour coverage on the old one goes unused.
The replay model behind the table
The script replays request times and prefix versions against the billing rules and prices in the assumptions. The trace at the end is Scenario E.
# Replay a request trace against OpenAI's documented cache billing for GPT-5.6+.
# Prices: USD per 1M tokens, gpt-6.1-sol, Standard tier, checked 2026-10-22.
PRICES = {"input": 2.00, "cached_input": 0.10,
"write_30m": 2.50, "write_12h": 5.00, "output": 10.00}
def replay(trace, ttl, prefix_tokens, tail_tokens, output_tokens, p=PRICES):
"""trace: list of (minute, prefix_version). ttl: "30m", "12h" or None."""
life = {"30m": 30, "12h": 720}.get(ttl)
expiry = {} # prefix_version -> minute the coverage ends
cost, hits = 0.0, 0
for minute, version in trace:
if ttl is None: # reference only: every prefix token at the input rate
cost += prefix_tokens * p["input"]
elif expiry.get(version, -1) >= minute: # read
hits += 1
cost += prefix_tokens * p["cached_input"]
expiry[version] = max(expiry[version], minute + 30)
else: # write
cost += prefix_tokens * p["write_" + ttl]
expiry[version] = minute + life
cost += tail_tokens * p["input"] + output_tokens * p["output"]
return round(cost / 1_000_000, 4), hits
# Two bursts of 10 requests, two hours apart, same 20,000-token prefix.
trace = [(start + i * 0.5, "v1") for start in (0, 120) for i in range(10)]
for ttl in (None, "30m", "12h"):
print(ttl, replay(trace, ttl, 20_000, 1_000, 500))Running it prints:
None (0.94, 0)
30m (0.276, 18)
12h (0.278, 19)To reproduce the other rows, change the trace; for D, give each burst its own prefix version. For your own workload, use timestamps and a prefix hash from your logs, and the current prices for your model.
What the replay model does not show
The replay model is optimistic. It assumes every request inside coverage is a read, and real traffic can miss. In a small test of gpt-5.5 (a model from before GPT-5.6) in the Responses API, Jangwook Kim found that on a prompt of about 3,700 tokens "roughly 1 in 4 calls still paid full price" (3 of 12 warm calls). The sample is small and predates GPT-5.6, so calibrate the replay model with the cached_tokens and cache_write_tokens your own responses report.
The replay model has other limits:
- No latency numbers. OpenAI's prompt caching guide does not quantify latency gains, and a minimum lifetime does not guarantee lower latency.
- Standard tier only. Cache-write columns do not appear in the Batch or Flex price tables.
- Responses API only. OpenAI documents the 12-hour option there, so do not plan on it for Chat Completions.
Testing the counterargument: more hits can only help
The case for switching: longer retention means more requests find the prefix warm, every extra hit is a read at a tenth of the input price or less, so turning 12h on can only help. On models before GPT-5.6, that holds. The longer 24h setting has no write charge, so extra retention costs nothing.
On GPT-5.6 and later it holds only when a prefix returns after two or more long gaps, because the longer option doubles the write price. Scenario E shows the small case: 12h raises the hit rate from 90.0% to 95.0%, and the bill rises by $0.002, under 1% of that trace. Scenario D shows the large case: the hit rates tie at 90.0%, and 12h costs 36% more.
Tian Pan described this pattern before the 12-hour option existed, writing about Anthropic prices: teams who "monitor the cache hit rate counter going up, and assume they're saving money. Some of them are paying more than if they hadn't cached anything."
What to log per request
Your dashboard gives you hit rate. The decision needs cost per prefix per window. To get it, log these fields for every request:
- Timestamp.
- Model and region.
- A hash or version label of the prefix.
- Billed input: total input tokens, from
usage.input_tokens. cached_tokens, fromusage.input_tokens_details.cache_write_tokens, with itscache_write_tokens_detailssplit intottl_30m_tokensandttl_12h_tokens.- Output tokens.
- Latency to first token, measured on your side.
Compute cost per request by pricing each bucket separately: uncached input, cached reads, 30-minute writes, 12-hour writes, and output. If you already track what each agent attempt costs, this is the caching line inside that number. Then group requests by prefix hash and 12-hour window, count G for each group, and compare the two formulas.
When a prefix misses unexpectedly, Prompt Cache Diagnostics compares a response with an earlier one through prompt_cache_options.comparison_response_id and returns a miss reason such as tools_changed or model_changed. It works on GPT-5.6 and later in the Responses API.
Know the limits of what you collect:
- Sample size: a few hours of traffic will not show a full week's gap pattern.
- Diagnostics records expire after a short period, so investigate misses soon.
- Caches cannot be reused across regional processing boundaries or shared across organizations, so one prefix served from two regions counts twice.
- List prices change, so store the price you used next to each calculation.
Workload audit checklist
- List every prefix your service sends that meets the minimum cacheable length (1,024 tokens on GPT-5.6 and later), with its model and API.
- Confirm which prefixes run on GPT-5.6 and later in the Responses API. Only those can use 12h.
- Move variable content, such as a timestamp, after the last breakpoint, and keep tools and output settings stable between requests.
- Record how often each prefix changes. A prefix that changes before each burst stays on 30m.
- Count G for each prefix in each 12-hour window from your logs.
- Check misses in your own
cached_tokensandcache_write_tokens, and run Diagnostics on unexpected ones. - Set 12h only on prefixes with G of 2 or more, and leave the rest on 30m.
- Replay or model a representative request trace with current prices before changing retention.
FAQ
No. The cache stores KV tensors for the reusable prefix at the start of the prompt, not the prompt tokens themselves. Caching does not change how the model generates output tokens.
OpenAI documents the 12-hour option for GPT-5.6 and later in the Responses API, through prompt_cache_options.ttl. Plan on the Responses API if you want 12h.
Not always on GPT-5.6 and later, because the 12h write costs 2.5x input instead of 1.25x. In modeled Scenario D, both options read the prefix on 90.0% of requests and 12h costs 36% more. In Scenario E, 12h raises the hit rate from 90.0% to 95.0% and still costs slightly more. Compare cost per prefix per window instead.
No. Set it only on stable prefixes that come back after two or more gaps longer than 30 minutes inside a 12-hour window. For steady traffic, or a prefix that changes often, the default 30m costs less.
Before you change retention on any prefix, pull a representative trace from your request logs, run it through the replay model with current prices, and check the result against the billing rules in OpenAI's prompt caching guide.






