Prompt caching
Prompt caching lets a provider reuse the tokens it already processed for a repeated prompt prefix instead of reading them again. Use it when many requests share a large, stable head, such as a long system prompt, a tool schema, a document you ask several questions about, or the growing history of a chat or coding-agent session. The cached prefix is billed at a lower rate and skips re-processing, so repeated requests are cheaper and start returning tokens sooner.
Gateway treats caching as a vendor-route capability. The same canonical model can cache differently depending on the vendor that serves the request, so the caching behavior follows the route, not the model name alone.
Caching never fails a request. If a route cannot honor a cache marker, Gateway removes the marker and sends the request normally rather than returning an error.
How prompt caching works
Every route falls into one of three caching families. The family decides what Gateway does with your request.
The split exists because providers disagree on how caching is triggered. Anthropic models need you to mark the cacheable prefix. Most other providers cache repeated prefixes automatically and reject the marker if you send it, so Gateway strips it for you rather than letting the request break.
Two things follow from this. Send cache_control markers only on explicit routes. On every other route, rely on automatic caching and skip the markers.
Which providers use which family
Routes not listed here are none today. A none route silently drops cache markers and bills every input token at the standard rate. Automatic caching is best-effort by the provider, so a given prompt may not produce a cache hit even on an automatic route, usually because the shared prefix is shorter than the provider’s minimum cacheable length.
Inputs: explicit caching with cache markers
On explicit routes, add a cache_control marker to the last content block of the prefix you want to reuse. Everything up to and including that block becomes the cached prefix. Put your stable content first (system instructions, tool definitions, a shared document), then the marker, then the part that changes per request.
The first request with a new prefix writes it to the cache and costs a small write premium. Every later request that repeats the same prefix reads it back at the discounted cache-read rate. The cache entry is short-lived, so caching pays off when repeat requests arrive close together, as they do in an agent loop or a multi-turn conversation.
You can place the marker on a text, image, document, or audio block. The block you mark, and everything before it, forms the cached prefix.
Let Anthropic place the marker for you
On Anthropic routes you can skip per-block markers entirely and send a single cache_control at the top level of the request body. Anthropic places the breakpoint on the last cacheable block and moves it forward as the conversation grows, so you do not rewrite markers on every turn. Gateway forwards the top-level marker unchanged.
This is still an explicit route, and the top-level field is still a marker. Anthropic does not cache anything you have not asked it to, so a request with no cache_control at all produces no cache hit no matter how long the shared prefix is. Do not confuse this with the automatic family below, where the provider caches on its own and Gateway strips markers.
Both styles compose. A top-level marker uses one of the four available breakpoints, so you can add per-block markers alongside it when you want to cache sections that change at different rates. Two constraints apply:
- A per-block marker with a different
ttlthan the top-level marker, on the block Anthropic would target, is rejected by Anthropic. Keep the TTLs the same or move the per-block marker earlier in the prompt. - Claude on Bedrock accepts a top-level marker on current model generations. Opus 4.6 and earlier on Bedrock reject it, so use per-block markers if your routing policy can land on one of those.
Inputs: automatic caching
On automatic routes, send the request as usual. The provider detects the repeated prefix and caches it without a marker. Keep the stable content at the front of the prompt so the reused prefix is as long as possible.
To help the provider group related requests onto the same cache, pass a session_id. Gateway namespaces it per organization and derives the provider cache key, so two of your requests with the same session_id land on the same cached prefix, and a different tenant’s identical value never collides with yours.
You can pass the session hint either as the X-Session-Id header or the session_id body field. The header wins when both are present. The value is capped at 256 characters and truncated rather than rejected, so a caching hint never fails a request.
Caching across API specs
Gateway accepts several request specs so you can point an existing SDK at it by changing the base URL. Each spec expresses caching in its own idiom, and Gateway normalizes them into the same caching contract. The X-Session-Id header works on every spec, since it rides on the HTTP request rather than the body.
Top-level markers are specific to the Anthropic request shape, so they are available on the Merge Responses API and the Anthropic SDK. The OpenAI and Vercel specs have no top-level field of their own, so place markers on a message or content block there.
The Merge Responses API examples are shown above. The rest of this section shows the same caching on the other specs.
Anthropic SDK
Point the Anthropic SDK at the /v1/anthropic base URL and mark the cacheable prefix with cache_control, the same way you would against Anthropic directly. Use this on explicit routes.
To let Anthropic place the breakpoint instead, pass a single top-level cache_control and leave the blocks unmarked:
If your SDK version does not accept cache_control as a named argument, pass it as extra_body={"cache_control": {"type": "ephemeral"}} instead. The SDK merges extra_body into the request body, so the field arrives at the top level either way.
OpenAI SDK
Point the OpenAI SDK at the /v1/openai base URL. The OpenAI request shape has no place for a session field in the body, so pass the caching session hint as the X-Session-Id header. This drives automatic caching on automatic routes.
Vercel AI SDK
Point the AI SDK at the /v1/ai-sdk base URL and attach the marker through providerOptions on the content part you want cached. Use this on explicit routes.
This page deliberately uses createOpenAICompatible rather than the native merge-gateway-ai-sdk-provider package: per-content-part cache markers are not yet forwarded by the native provider, and this shim path is the supported way to send them today.
Whichever spec you use, the response reports cache activity the same way, covered next.
Outputs: reading cache token usage
Gateway reports cache activity in the response usage object, normalized across providers so you read the same two fields regardless of the route.
A first request that writes the prefix reports a positive cache_creation_input_tokens and a cache_read_input_tokens of 0. A later request that hits the cache reports a positive cache_read_input_tokens. On automatic routes the provider may report only reads.
On the OpenAI-shaped surfaces
/v1/openai/chat/completions, /v1/ai-sdk/chat/completions, and the LangChain surface report cache reads using OpenAI’s own field, so cache-aware clients and observability tooling read it without special-casing Gateway.
prompt_tokens_details is absent when the route did not serve anything from cache, so a missing field means “not cached” rather than “cached zero tokens”. It is reported on both streaming and non-streaming responses; on a stream it arrives on the final chunk with the rest of usage.
These surfaces report cache reads only. For the write side (cache_creation_input_tokens), read usage from /v1/responses or /v1/anthropic, which expose both fields.
Cache-read tokens are billed at the route’s reduced cache-read rate instead of the standard input rate, which is where the savings come from. Track cache_read_input_tokens across your traffic to measure the hit rate and the spend you avoid. For budgets and spend reporting, see Cost governance and savings.
Get the most out of caching
- Put stable content first. Order the prompt so the unchanging part (system instructions, tool schemas, shared documents) comes before the part that changes each request. The cached prefix ends at the first token that differs.
- Reuse prefixes while they are warm. Cache entries are short-lived. Caching pays off most in agent loops and multi-turn chats where repeat requests arrive within seconds.
- Keep the prefix long enough. Providers only cache prefixes above a minimum length. A short shared prefix produces no cache hit even on a caching-capable route.
- Pin
modelandvendorwhen caching matters. Caching follows the route. A routing policy that can pick anoneroute for some requests will not cache those, so pin the route when you depend on cache hits.
Common errors
I sent cache_control but usage shows no cache tokens
The route may be automatic or none, where Gateway strips the marker. Check the family for your provider in the table above. On automatic routes, remove the marker and rely on the provider caching the prefix on its own.
cache_read_input_tokens is always zero on an explicit route
The cache entry may have expired between requests, the prefix may be shorter than the provider minimum, or the prefix may differ across requests. Confirm the marked content is byte-for-byte identical and that repeat requests arrive close together, then verify the marker sits on the last block of the stable prefix.
A top-level cache_control returns a 400 on Bedrock
Claude on Bedrock accepts a top-level marker on current model generations, but Opus 4.6 and earlier reject it and return an unsupported-model error from Bedrock. Those models still accept per-block markers. If your routing policy spans model generations, use per-block markers so one payload works across every route.
I get a ttl mismatch error when I mix marker styles
Anthropic rejects a request where the top-level marker and the block it targets carry different ttl values. Either match the TTLs, or move the per-block marker earlier in the prompt so it is not the block Anthropic would target.
Caching does not seem to work through my routing policy
A policy that selects among several routes can land on one that does not cache. Pin model and vendor for requests that depend on cache hits, or configure the policy with routes that share the same caching family.