Turn caching on, then prove it works
Adding a cache marker is the easy part. The step that matters is verification. A cache that never reads costs you money. On some providers you pay a write premium on every call and get no discount back. This guide walks the five steps end to end, with the exact field to check for each provider.
Most guidance on prompt caching stops at “add the cache marker.” What goes wrong after that is silent: you add the marker, the request still succeeds, the bill does not move, and nothing tells you why. On a provider that charges a premium to write a cache entry, a cache that never gets read is worse than not caching at all. You pay the write premium on every call and collect none of the read discount in return.
Enabling caching takes five steps, and checking that it works is the one that matters most. Structure a stable prefix, turn caching on the way your provider requires, confirm from the response that the cache is being read, measure the net saving, and keep the prefix from silently breaking. Whether caching will pay off on your workload at all is covered in Prompt Caching Explained. Prices and sizes here are dated and linked to the provider’s own documentation, so recheck them before you rely on them.
The running example throughout is a coding agent: a fixed system prompt, a large set of tool definitions, and repository context that repeat on every step, with only the newest user turn changing. That is the best case for caching: a big stable prefix reused many times in quick succession.

Step 1: Confirm the prerequisites
Before you touch any caching parameter, two things have to be true, and if either is false, caching cannot help yet.
Your request must have a stable leading prefix that repeats across calls. Caching matches the beginning of a request, in order, from the first token, and stops at the first token that differs. So the technique cares about where content sits. Repeated content that sits behind something that changes earns nothing. The coding agent qualifies: its system prompt, tool definitions, and repository context are identical on every step of a session. A stream of unrelated one-shot prompts does not; there is no shared prefix to reuse.
That prefix must clear the model’s minimum cacheable size. Below that per-model minimum, the provider stores nothing, your request still succeeds, and no error is returned. The only symptom is a cache-read counter that never leaves zero. As of October 8, 2026, the minimums are:
- Anthropic: 512 tokens for Claude Opus 5.5, Claude Sonnet 5.5, Claude Haiku 5.5, Claude Fable 5.1 and Claude Mythos 5.1; 1,024 for Claude Opus 4.8 and Claude Sonnet 5; other models differ, per the prompt caching documentation.
- OpenAI GPT-5.6 and later: 1,024 visible prefix tokens, with implicit breakpoints by default and optional explicit breakpoints, per the prompt caching guide.
- Amazon Bedrock: per model, per cache checkpoint: 1,024 tokens for Claude 3.7 Sonnet and Claude Sonnet 4.5, 4,096 for Claude Opus 4.5, per the Bedrock prompt caching guide.
- Google Gemini: 2,048 to 4,096 tokens depending on the model, per the context caching documentation.
You also need API access to the response’s usage object, because Step 4’s verification depends on reading the token counts it reports. Every provider covered here returns them by default.
Step 2: Identify the stable prefix and the volatile tail
Caching operates on a contiguous prefix, so the single most important structural decision is the order of your request: everything that is identical across calls goes at the front, everything that changes goes at the end. The boundary between them is where a cache marker belongs.
For the coding agent, the stable prefix is the system prompt, the tool definitions, and the repository context, in a fixed order. The volatile tail is the newest user turn and the latest tool result. Mark the boundary at the last token that is identical across requests. Not earlier, which leaves cacheable content uncached, and not inside the volatile region, which breaks the match on every call.
The failure that hides here is a single volatile value that has drifted forward into the prefix. A timestamp injected into the system prompt, a request id rendered near the top, a per-user greeting ahead of the shared context, or a JSON object serialized with non-deterministic key order. Any one of these changes the leading bytes and forces a fresh write every time, so the cache never reads. The fix is to move the volatile value behind the boundary so the prefix stays byte-for-byte identical.

Step 3: Enable it for your provider
Each provider turns caching on differently, and some need no marker at all.
OpenAI implicit caching: no marker required. OpenAI places breakpoints
automatically when the prefix meets the model’s minimum (see the
OpenAI guide).
Cache hits require a matching prefix, so keep stable content first. On GPT-5.6
and later, a cache write costs 1.25× ordinary input. If requests share a
stable prefix but end with different user content, place an explicit breakpoint
after the shared prefix and set prompt_cache_options.mode to "explicit". In
the default implicit mode the automatic breakpoint still applies alongside
yours, and it can include the changing suffix and produce another write instead
of a hit.
Anthropic and Amazon Bedrock: automatic or marked. Both can place the cache boundary for you, and both let you mark it yourself when you want control over what gets cached. Either way, a write can be billed above the normal input rate.
-
Anthropic accepts a single top-level
cache_controlfield that places the breakpoint on the last cacheable block and moves it forward as the conversation grows. For explicit control, put acache_controlobject on the content block at the boundary instead. The default entry lives five minutes; adding"ttl": "1h"requests a one-hour entry at a higher write rate. A request can hold up to four breakpoints, and automatic placement uses one of them. As of September 22, 2026, per the prompt caching documentation:{ "type": "text", "text": "<system prompt, tool definitions, repository context>", "cache_control": { "type": "ephemeral" } } -
Amazon Bedrock caches Claude prompts implicitly, on a best-effort basis, with no marker. For explicit control it uses a
cachePointmarker in the Converse API, placed in thesystem,messages, ortoolsfields after the stable content; in the InvokeModel API for Claude models it uses the samecache_controlobject. A one-hour TTL goes incachePointon Converse and incache_controlon InvokeModel, for supported models. Checkpoints are processedtools→system→messages, and changing an earlier section invalidates the later ones, so place stable sections first. As of September 22, 2026, per the Bedrock guide:"cachePoint": { "type": "default" }
Google Gemini: implicit, or a separate cache object. Gemini 2.5 and newer models cache implicitly by default, applying a discount when a prefix matches with no configuration, and the Interactions API supports only this implicit mode. Explicit caching is available only on the older generateContent API. Instead of a per-request marker, you create a cache object in its own API call, get back a handle, and reference that handle on later requests, closer to an “upload it first” model. As of September 22, 2026, see the caching documentation and the generateContent caching guide.
Step 4: Verify the cache is being read
Adding a cache marker asks the provider to cache. It does not confirm the provider did, or that later requests are reusing what it stored. The response’s usage object answers that directly.
Send the same-prefix request twice. The first request writes the entry; the second should read it. On the second response, read the cache-read field:
- Anthropic:
cache_read_input_tokens(tokens served from cache) andcache_creation_input_tokens(tokens written);input_tokenscounts only the uncached remainder. - OpenAI:
cached_tokensand, on GPT-5.6 and later Responses API calls,cache_write_tokensunderusage.input_tokens_details. Chat Completions responses putcached_tokensunderusage.prompt_tokens_details. - Amazon Bedrock:
cacheReadInputTokensandcacheWriteInputTokens;inputTokenscounts only the non-cached remainder. - Google Gemini:
usage.total_cached_tokenson the Interactions API; on the generateContent API, the cached-content token count underusageMetadata(usage_metadatain the Python SDK).
A non-zero, growing cache-read count across repeated requests is the proof that caching engaged. Zero on the second request means it did not, and now you know before the bill arrives. Read the write counter too: a non-zero write on the first request followed by a zero read on the second tells you the entry was stored but not matched, which points at a broken prefix rather than a below-minimum one.
One caution from doing this ourselves. On a July 2026 run we derived a read ratio of 91.6% from these counters while the Claude Console reported 99.9% for the same requests. The difference was the denominator: we had counted the one-time cache write as input, and the Console leaves writes out. Compare counters to counters, and treat any percentage you compute as a different number from the one a provider renders until you know what it divides by.

Step 5: Measure the net saving
On a model that charges a cache-write premium, you paid extra to write the entry, and that premium has to be earned back by enough cheap reads before the entry’s TTL expires. Confirming a read (Step 4) and confirming a net saving (this step) are different checks, and it is possible to pass the first and fail the second: a prefix read only once or twice before it expires can cost more with caching than without.
You already have the inputs: the token counts from Step 4. To measure the saving over a reuse window, price what happened against what you would have paid with caching off, using multipliers relative to the normal input rate:
- Caching path = (cache-write tokens × write multiplier) + (cache-read tokens × read multiplier) + (uncached tokens × 1).
- No-caching path = (all input tokens × 1), for the same requests.
The multipliers are the provider’s, dated. As of October 8, 2026, Anthropic prices a five-minute cache write at 1.25× the input rate and a one-hour write at 2×. The cache-read multiplier now has three tiers: 0.1× input for most Claude models (Claude Haiku 5.5 included), 0.05× for Claude Opus 5.5 and Claude Sonnet 5.5, and 0.025×, one-fortieth of input, for Claude Fable 5.1 and Mythos 5.1, per the prompt caching documentation. For GPT-5.6 and later, OpenAI charges 1.25× for cache writes and 0.1× for cache reads on most models, 0.05× on GPT-6.1 Sol, per its prompt caching guide. Plug your own reported counts into both lines and the sign of the difference is your answer. On the coding agent, one write of a large prefix at 1.25× followed by many discounted reads crosses below the all-input-rate line after the first couple of reads, and the gap widens with every further reuse, which is the break-even curve the concept guide derives and measures in money. This guide keeps it in rate multipliers so the arithmetic is portable across models and dates.
Over time, two signals confirm the saving is holding without redoing the sum on every request: the cached-token share of your input rising toward the stable-prefix fraction you expect, and the cost-per-request falling at steady usage. If you enabled caching and neither moved, the prefix is probably not matching; go back to Step 4.
When the counter stays at zero
If Step 4 returns zero reads, the loop closes back to Steps 1 and 2, and almost always to one of three causes. Work them in order:
- The prefix is below the minimum. Check that the tokens ahead of your marker clear the model’s minimum from Step 1. Below it, nothing is stored, so the read counter stays at zero, and so does the write counter where the API reports one. Enlarge the stable prefix or confirm you are on the model whose minimum you assumed.
- A volatile value is breaking the prefix. If the write counter is non-zero but the read counter is not, the entry is being stored and never matched. Diff the rendered bytes of two “identical” requests and look for a timestamp, id, per-user string, or reordered JSON near the front. Move it behind the boundary. A miss can also come from the entry expiring, or from the request reaching a different cache than the one that stored it, so rule those out before you hunt for a changed byte.
- Reuse is slower than the TTL. If both counters look healthy in a tight test but production shows few reads, your requests are arriving further apart than the entry lives, so it expires between calls. Cluster requests that share a prefix inside the TTL window, or where supported, request a longer TTL.
This is the “keep the prefix from breaking” step, and it is ongoing rather than one-time: a later change that injects a per-request value into the prefix will silently undo caching, and the only thing that catches it is the cache-read counter you now know how to read. Wire that counter into whatever you already watch, so a regression shows up as a metric. When the counter is stuck and the three causes above don’t explain it, Why your prompt cache isn’t working is the full diagnostic reference: the same write / read / economics decision tree, with the read-side failure localized to the exact request segment that broke.
Where to watch it over time
Once caching is on and verified, the job shifts from enabling to monitoring, and the two signals that matter, cached-token share and cost-per-request, live inside each provider’s usage data. On a single provider you can read them from the usage object directly. On Claude, the Console’s Caching page charts cached-token share and write amortization for you (How to read Claude’s cache usage dashboard). Across several providers they are scattered across different billing pages with different field names, which is where pulling cached-versus-uncached usage into one place helps; tracking AI costs across providers covers that, and CostCompass pulls billed spend from your connected providers into one running total, split by model, so you can see whether caching moved the bill; cached-token share itself still comes from each provider’s usage data. Caching is also one lever among several. It composes with routing requests to cheaper models and centralizing policy through a gateway, both placed in context by The Hidden Economics of AI Coding.
The marker was never the hard part. Structure the prefix, enable it, confirm the read counter, measure the net, and keep the prefix from breaking.
Frequently asked questions
- I added cache_control but cache_read_input_tokens is still zero. Why?
- A zero read count means the provider never matched your prefix against a stored entry. Three causes account for almost all of it. First, the prefix is below the model's minimum cacheable size, so nothing was stored. Check that the tokens before your breakpoint clear the model's minimum (as of September 28, 2026, 512 tokens for Claude Opus 5.5, Sonnet 5.5, Fable 5.1 and Mythos 5.1, and 1,024 for Claude Opus 4.8 and Sonnet 5 on Anthropic's direct API, higher for some models). Second, a value near the front of the request changes on every call (a timestamp, a request id, a per-user string, or non-deterministic JSON key order), which resets the match; move anything volatile to the tail. Third, your reuse is slower than the cache's TTL, so the entry expires between calls and each request writes a fresh one. Confirm the first request wrote (a non-zero cache_creation_input_tokens) before assuming the read path is the problem.
- What is the minimum number of tokens before prompt caching does anything?
- There is a minimum size below which the provider stores nothing, and it depends on the model, not just the provider. As of September 28, 2026, Anthropic requires 512 tokens for Claude Opus 5.5, Sonnet 5.5, Fable 5.1 and Mythos 5.1, and 1,024 for Claude Opus 4.8 and Sonnet 5, with different minimums for other models; OpenAI requires 1,024 visible prefix tokens for GPT-5.6 and later, while earlier models vary with request settings; Amazon Bedrock's minimum is per-model per cache checkpoint (1,024 tokens for Claude 3.7 Sonnet and Sonnet 4.5, 4,096 for Claude Opus 4.5); Google Gemini's minimum ranges from 2,048 to 4,096 tokens depending on the model. Below the minimum your request still succeeds, but nothing is cached and no error is returned, so the only signal is a cache-read counter stuck at zero. Always check the current number against the provider's own documentation before you plan around it.
- Do I need to change my code to get prompt caching on OpenAI?
- No for the default implicit mode. OpenAI places cache breakpoints automatically when the prefix meets the model's minimum length. For GPT-5.6 and later, you can also place explicit breakpoints and set prompt_cache_options.mode to explicit so only your breakpoints are used, which avoids writing changing content; cache writes cost 1.25 times the ordinary input rate, while reads cost one-tenth on most of these models and one-twentieth on GPT-6.1 Sol. Keep stable content first, then measure both writes and reads. Anthropic and Amazon Bedrock each offer automatic caching for Claude as well as markers you place yourself, with their own rates.
- How do I make a cached prompt last longer than five minutes?
- Where the provider supports it, you request a longer time to live (TTL) when you write the entry. On Anthropic and on Amazon Bedrock for supported models, add "ttl":"1h" to get a one-hour entry instead of the default five minutes. It goes in the cache_control object on Anthropic and on Bedrock's InvokeModel API, and in the cachePoint object on Bedrock's Converse API (as of September 22, 2026). The longer entry is billed at a higher write rate. Whether the longer TTL pays for its higher write premium depends on how often you reuse the prefix. The companion guide, Prompt Caching Explained, walks through when a longer window pays for itself. If reuse is faster than five minutes, the default TTL already refreshes on each hit at no extra charge, so you usually do not need the longer window.
- How do I know if prompt caching is saving money and not just working?
- Those are two separate checks, and passing the first does not guarantee the second. A non-zero, growing cache-read counter proves the mechanism engaged. The provider stored your prefix and is reusing it. It does not prove the workload is net-cheaper, because on a model that charges a cache-write premium the write premium you paid up front still has to be earned back by enough cheap reads before the entry expires. To measure the saving, take the reported cache-read and cache-write token counts, price the reads at the cache-read rate and the writes at the write-premium rate, and compare the total against pricing every token at the normal input rate over the same reuse window. Watch two signals over time. Cached-token share should rise toward the stable-prefix fraction you expect, and cost-per-request should fall at steady usage.
About the author
Joubert Berger builds CostCompass, a spend-intelligence dashboard that pulls usage from AI and compute providers into one month-to-date total, a forecast, and a per-provider breakdown. This guide reflects how CostCompass reads each provider's own usage API — see the security model for how your keys are handled.
See whether caching moved your bill
Once caching is on, the signals that tell you it is still working (cached-token share rising, cost-per-request falling) live in each provider's usage data. CostCompass pulls billed spend from your connected providers into one running total, split by model, so you can see whether the bill went down when you look.