TL;DR
Published September 1, 2026. Provider rates were fetched from each vendor's pricing page on that date; Morph rates come from the same pricing table that bills the API.
“prompt tokens prefilled across one 30-turn coding-agent session with a 20k-token system prompt, to produce 15,000 output tokens. Prompt caching is what keeps that ratio affordable.”
Prompt caching is the reuse of a model's KV cache for a prompt prefix it has already processed. A request that begins with the same tokens as an earlier request skips prefill for the matching prefix and bills those tokens at a cached-input rate. Every major provider now sells it: 0.1x base input on Anthropic (0.025x on Claude Fable 5.1), OpenAI GPT-5.6, Gemini 3.x, and Moonshot Kimi K3, 0.032x on DeepSeek V4 off-peak, and $0.26 against $1.25 per 1M on GLM-5.3 744B at Morph. The mechanics are the same everywhere. The write surcharges, minimum prefix sizes, and retention windows are not.
What it saves
A 30-turn agent session with a 20k-token prefix sends 1,252,500 prompt tokens. At a 90% hit rate on GLM-5.3 744B it costs $0.516 instead of $1.63. On DeepSeek V4 Flash it costs $0.056 instead of $0.160. Exact replay reaches about 95% hits.
What breaks it
A changed byte in the prefix, a different worker, or a different model. Each model has its own cache, so a router that re-picks the model per turn re-prefills the whole context: 41,000 tokens at turn 15 cost $0.051 to move to GLM-5.3 744B versus $0.001 to continue warm on DeepSeek V4 Flash.
How Prompt Caching Works
A transformer answers a prompt in two phases. Prefill reads every prompt token and computes a key and a value vector per token per layer, the KV cache. Decode then produces output tokens one at a time, attending to that cache. Prefill is compute-bound: its cost grows with prompt length, and for a coding agent the prompt is the entire conversation so far. Decode is memory-bound and produces a few hundred tokens per turn. On the session above, prefill handles 1,252,500 tokens and decode handles 15,000. Prefill is where the money goes.
Prompt caching keeps the KV cache from prefill and reuses it. Three rules define what can be reused:
- Exact prefix match. Attention at position n depends on every token before n. The cache for a token is only valid if all preceding tokens are identical. A request therefore hits from token zero up to the first token that differs from the cached prefix, and never past it.
- Block alignment. Engines store the KV cache in fixed-size blocks and hash whole blocks. Morph caches on roughly 1k-token blocks. A matching prefix that ends mid-block reuses the complete blocks before it; the partial block is prefilled again. Very short prompts have no full block to reuse, which is why every provider publishes a minimum cacheable length.
- Locality. The cache is GPU memory (sometimes tiered to CPU or NVMe) on the worker that ran the prefill. A request only hits if it reaches that worker while the blocks are still resident. Retention is bounded either by a TTL or by LRU eviction under memory pressure.
Multi-turn agent loops are the ideal shape for this. Each turn re-sends the previous turns verbatim and appends one new message, so the entire prompt except the newest turn is a prefix the engine has already processed. The provider reports how much hit in the usage object; on Morph it is usage.prompt_tokens_details.cached_tokens, and the remainder of prompt_tokens bills at the input rate.
For the serving side of the same story, throughput, batching, and where the KV cache lives across GPU, CPU, and NVMe, see LLM inference. For the KV-cache memory techniques that make long prefixes cheap to hold, see grouped-query attention and FP8 quantization.
Prompt Caching Pricing by Provider
Every number below was read from the vendor's own docs on September 1, 2026 (links in Sources). The cache read multiplier is cached input divided by base input. One representative model per vendor keeps the table readable; the same multipliers apply across each vendor's current lineup unless noted.
| Provider / model | Input | Cached input | Read multiplier | Write surcharge | Opt-in | Retention | Min prefix |
|---|---|---|---|---|---|---|---|
| Anthropic, Claude Sonnet 5 | $2.00 | $0.20 | 0.1x | 1.25x (5m TTL), 2x (1h TTL) | cache_control breakpoints | 5m default, 1h option, refreshed on hit | 1,024 tokens |
| Anthropic, Claude Fable 5.1 | $10.00 | $0.25 | 0.025x | 1.25x (5m), 2x (1h) | cache_control breakpoints | 5m default, 1h option | 512 tokens |
| OpenAI, GPT-5.6 Terra | $2.00 | $0.20 | 0.1x | None | Automatic; prompt_cache_key steers routing | 30 min after last write or reuse | 1,024 tokens |
| Google, Gemini 3.5 Flash | $1.50 | $0.15 | 0.1x | None (implicit); explicit caches bill $1.00 per 1M tokens per hour of storage | Implicit automatic on 2.5+; explicit CachedContent optional | Implicit: recent requests; explicit: your TTL | 4,096 tokens (implicit) |
| DeepSeek, deepseek-v4-flash (off-peak) | $0.22 | $0.007 | 0.032x | None | Automatic | Cleared when unused, hours to days | Full prefix match; interval not published |
| Moonshot, kimi-k3 | $3.00 | $0.30 | 0.1x | None | Automatic | Not published | Not published |
| Morph, GLM-5.3 744B (morph-glm53-744b) | $1.25 | $0.26 | 0.208x | None | Automatic; prompt_cache_key or x-session-id pins the worker | LRU, no expiry; or cache_ttl 5m to 24h, sliding | About one 1k block |
| Morph, GLM-5.3-Flash (morph-glm53flash) | $0.13 | $0.02 | 0.154x | None | Automatic; prompt_cache_key or x-session-id pins the worker | LRU, no expiry; or cache_ttl 5m to 24h, sliding | About one 1k block |
| Morph, Kimi K3 2.8T (morph-kimik3) | $2.50 | $0.29 | 0.116x | None | Automatic; prompt_cache_key or x-session-id pins the worker | LRU, no expiry; or cache_ttl 5m to 24h, sliding | About one 1k block |
| Morph, DeepSeek V4 Flash 0731 (morph-dsv4flash) | $0.1234375 | $0.03125 | 0.253x | None | Automatic; prompt_cache_key or x-session-id pins the worker | LRU, no expiry; or cache_ttl 5m to 24h, sliding | About one 1k block |
Two things stand out. First, the read multiplier has converged on 0.1x, with DeepSeek below it and Morph's DeepSeek V4 Flash and GLM-5.3 744B above it in ratio terms but far below it in absolute price: $0.03125 per 1M cached input on morph-dsv4flash is the lowest cached rate in the table after DeepSeek's own off-peak window, and Morph has no peak window (DeepSeek doubles every rate from 01:00 to 04:00 and 06:00 to 10:00 UTC on weekdays). Second, only Anthropic charges to write. A 1.25x write means a prefix must be read at least once more to break even against not caching; at 2x for the 1-hour TTL it must be read twice. Everyone else caches speculatively for free.
Per-vendor detail lives on the model pages: Anthropic API pricing, OpenAI API pricing, Gemini API pricing, DeepSeek API, and Kimi K3 API.
Worked Example: A 30-Turn Coding Agent
The session: a 20,000-token system prompt plus tool definitions, byte-identical every turn. Each turn appends 1,500 tokens of user message, tool results, and assistant reply, and the model writes 500 output tokens. 30 turns. Turn n re-sends the prefix plus n minus 1 turns of history, so prompt tokens across the session sum to 1,252,500. The "90% hits" column bills 1,127,250 of those at the cached rate and 125,250 at the input rate.
| Line | No cache | 90% hits | Arithmetic |
|---|---|---|---|
| Prompt tokens | 1,252,500 | 1,252,500 | 30 x 20,000 + 1,500 x (0 + 1 + ... + 29) |
| Uncached input | $1.57 | $0.157 | 125,250 x $1.25 / 1M |
| Cached input | $0.00 | $0.293 | 1,127,250 x $0.26 / 1M |
| Output | $0.066 | $0.066 | 15,000 x $4.40 / 1M |
| Session total | $1.63 | $0.516 | 68% lower |
| Line | No cache | 90% hits | Arithmetic |
|---|---|---|---|
| Prompt tokens | 1,252,500 | 1,252,500 | same session |
| Uncached input | $0.155 | $0.015 | 125,250 x $0.1234375 / 1M |
| Cached input | $0.000 | $0.035 | 1,127,250 x $0.03125 / 1M |
| Output | $0.005 | $0.005 | 15,000 x $0.3475 / 1M |
| Session total | $0.160 | $0.056 | 65% lower |
90% is conservative for this shape. With exact replay only the first prefill (20,000 tokens) and each later turn's new 1,500 tokens miss: 63,500 of 1,252,500, a 95% hit rate. Anything below 90% on a loop like this means the prefix is changing or the requests are landing on different workers. The usage object on the final turn of an exact-replay session looks like this:
Turn 30 usage, exact replay
{
"usage": {
"prompt_tokens": 63500,
"completion_tokens": 500,
"total_tokens": 64000,
"prompt_tokens_details": { "cached_tokens": 62000 }
}
}62,000 of 63,500 prompt tokens bill at $0.03125 per 1M on morph-dsv4flash; the 1,500 new tokens bill at $0.1234375. Output is unaffected: caching never touches the decode side of the bill. If your agent's output share is large (always-on reasoning models like Kimi K3 emit long reasoning traces), caching cuts the input line and leaves the output line alone. For the full set of levers on the rest of the bill, see LLM cost optimization and Claude Code token usage.
Cache-Aware Routing: Why a Naive Router Destroys the Hit Rate
An LLM router classifies a prompt and picks the cheapest model that can handle it. Applied per turn to a multi-turn session, it fights prompt caching in two ways.
- Each model has its own cache. A KV cache is a function of the weights. The prefix GLM-5.3 prefilled is useless to DeepSeek V4 Flash. The first turn on a new model prefills the whole conversation at that model's input rate.
- Within a model, the cache is per worker. A load balancer that spreads a conversation across replicas round-robin turns a 95% replay into a hit rate near 1 divided by the replica count. Session affinity, a stable mapping from conversation to worker, is what makes the automatic cache deliver.
At turn 15 of the example session the context is 41,000 tokens. Continuing on morph-dsv4flash serves those tokens from cache for $0.001. Switching to morph-glm53-744b prefills them fresh for $0.051, about 40x, before the turn produces a single output token. Switch back on turn 16 and you pay the DeepSeek input rate on the whole context again if its blocks were evicted in the meantime. A router that saves a per-token rate difference by switching can come out behind on every switch.
Route once, at the session boundary
The first turn of a session is the one moment a switch is free, because nothing is cached yet. Morph's Model Router classifies difficulty, ambiguity, and domain in one call at $0.005 per request, returns the model to call from a candidate list you pin, and then gets out of the way. Every later turn reuses the decision and carries the same session key, so both the model and the worker stay fixed.
Classify once per session, then pin model and worker
import os
import requests
from openai import OpenAI
MORPH_API_KEY = os.environ["MORPH_API_KEY"]
client = OpenAI(api_key=MORPH_API_KEY, base_url="https://api.morphllm.com/v1")
CANDIDATES = ["deepseek-v4-flash", "glm-5.2"] # two tiers, not ten
_session_model: dict[str, str] = {}
def model_for_session(session_id: str, first_turn: str) -> str:
# Route once, at the session boundary, when nothing is cached yet.
if session_id in _session_model:
return _session_model[session_id]
resp = requests.post(
"https://api.morphllm.com/v1/router/multimodel",
headers={"Authorization": f"Bearer {MORPH_API_KEY}"},
json={
"input": first_turn,
"allowed_models": CANDIDATES,
"policy": "cost_efficient",
"default_model": "glm-5.2",
},
timeout=5,
)
_session_model[session_id] = resp.json()["model"]
return _session_model[session_id]
def handle_turn(session_id: str, messages: list[dict]):
model = model_for_session(session_id, messages[-1]["content"])
return client.chat.completions.create(
model=model,
messages=messages,
extra_body={"prompt_cache_key": session_id},
)Two or three candidates is the right size. Every extra candidate is another cold cache the router can dump a session into. Re-classify only at boundaries you are already paying for: a new session, or a context compaction that rewrote the prefix anyway. Morph's Claude Code proxy ships this as a context lock: past 60k tokens of context it stops classifying and holds the session's model, because at that size prefill dominates any per-token rate difference.
Pin the worker with a session key
Caching on Morph needs no key. The key answers the other question: which worker serves the turn. Send one id per conversation as the prompt_cache_key body field or the x-session-id header, on every turn and on retries of the same turn, and each request routes to the worker that already holds its prefix. OpenCode and the Codex CLI already send prompt_cache_key; OpenRouter forwards x-session-id on behalf of its callers. The key changes placement, never billing. cache_ttl is independent: it controls how long that worker keeps the prefix, sliding, in five tiers from 5m to 24h. Invalid values are rejected with a 400.
Session key and TTL, Python (OpenAI SDK)
from openai import OpenAI
client = OpenAI(
api_key="YOUR_MORPH_API_KEY",
base_url="https://api.morphllm.com/v1",
)
# One id per conversation, generated when it starts, reused on every
# turn and on retries of the same turn. It pins placement, not billing.
SESSION_ID = "conv-8f2c1a"
response = client.chat.completions.create(
model="morph-dsv4flash",
messages=messages, # system, tools, full history, newest message last
extra_body={
"prompt_cache_key": SESSION_ID,
"cache_ttl": "1h", # sliding: every hit refreshes the clock
},
)
usage = response.usage
cached = usage.prompt_tokens_details.cached_tokens
print(f"{cached}/{usage.prompt_tokens} prompt tokens served from cache")Same key as a header, cURL
curl -X POST "https://api.morphllm.com/v1/chat/completions" \
-H "Authorization: Bearer YOUR_MORPH_API_KEY" \
-H "x-session-id: conv-8f2c1a" \
-H "Content-Type: application/json" \
-d '{
"model": "morph-glm53-744b",
"messages": [{"role": "user", "content": "..."}],
"cache_ttl": "6h"
}'One key across an app funnels every request onto one worker. That worker fills, sheds overflow with 429s, and the retries cost more than the cache saved. Generate the key when the conversation starts and scope it to that conversation. Keys are hashed server-side; the raw value is never stored.
Escalate a turn without losing the cheap prefix
Some turns in a cheap session genuinely need the stronger model. The mistake is to move the session. Instead, run the hard turn on the strong model under its own session key, append its answer to the shared history, and continue the next turn on the cheap model. Appending never invalidates a prefix: the cheap model's cached blocks still match through the last turn it served, and only the new assistant message and the next user message prefill. The strong model pays one full prefill, which is the price of the escalation, not a recurring tax. If escalations become frequent, the classifier was wrong about the session; re-route at the next compaction.
Per-turn escalation with two warm prefixes
CHEAP = "morph-dsv4flash"
STRONG = "morph-glm53-744b"
def handle_turn(session_id: str, messages: list[dict], hard: bool):
# The cheap model keeps its warm prefix under the session key.
# A hard turn runs on the strong model under its own key. Its answer
# is appended to the shared history, so the cheap model's prefix is
# still an exact match on the next turn: append never breaks a hit.
model = STRONG if hard else CHEAP
key = f"{session_id}:{model}"
reply = client.chat.completions.create(
model=model,
messages=messages,
extra_body={"prompt_cache_key": key, "cache_ttl": "1h"},
)
messages.append({"role": "assistant", "content": reply.choices[0].message.content})
return replyThe same rule governs multi-agent layouts: give each subagent its own session key and its own stable prefix rather than sharing one conversation across models. See multi-agent model routing and, for Claude Code specifically, Claude Code Router.
Rules for a High Hit Rate
Stable prefix first
Order the prompt system prompt, then tool definitions, then history, then the newest message. Retrieved context and anything per-request goes last. A cache matches from token zero forward, so the variable part must sit at the end.
No timestamps, IDs, or names in the prefix
A clock, request ID, user name, or random example in the system prompt changes a byte in block one and ends the match at token zero. Put per-request metadata in the last user message or leave it out.
Think in 1k-token blocks
Morph caches on roughly 1k-token blocks; Anthropic and OpenAI will not cache prompts under 1,024 tokens (4,096 on Gemini 3.x and Claude Haiku 4.5). A 300-token prompt has nothing to reuse. A 20k-token prefix that grows 1.5k per turn reuses about 20 blocks on turn 2 and more on every turn after.
Replay turns verbatim, append only
Multi-turn loops hit because each turn re-sends the earlier turns unchanged. Trimming, summarizing, or reformatting an earlier message invalidates everything after it. When context must shrink, compact once at a clean boundary and treat it as a new prefix.
Deterministic tool serialization
Serialize tool definitions in a fixed order with stable JSON key ordering. A framework that rebuilds the tool list from a set or map each turn can reorder it silently and move the divergence point up to the tool block.
One session key per conversation
Send the same prompt_cache_key or x-session-id on every turn and every retry so the request reaches the worker that holds the prefix. Never reuse one value across unrelated traffic.
Measure, do not assume. Log cached_tokens divided by prompt_tokens per request and alert when a session's ratio drops below the replay expectation. On Anthropic the equivalent fields are cache_read_input_tokens and cache_creation_input_tokens; on DeepSeek, prompt_cache_hit_tokens and prompt_cache_miss_tokens. Claude Code exposes the same ratio in /cost.
Pitfalls
Kimi K3 needs reasoning_content replayed verbatim
Kimi K3 thinks on every turn and is trained to see its own prior reasoning. Moonshot's quickstart requires adding the complete assistant message to the next request, reasoning_content and tool_calls included, not content alone. Harnesses that strip the thinking to save tokens degrade the model and, because the stripped history differs from what the model saw, still miss the cache. Replay it and the prefix grows, which is exactly what $0.29 per 1M cached input on morph-kimik3 (against $2.50 uncached) is for. Details on the Kimi K3 API page.
Tool definitions that drift
Tool schemas usually sit right after the system prompt, so a change there invalidates nearly everything. Common causes: an MCP server that re-registers tools with a new description on reconnect, a framework that dedupes tools through a set and loses order, or a dynamic tool loader that injects a per-turn subset. If tools must vary per turn, place the variable subset after the stable ones.
Streaming retries
A stream that drops mid-generation is usually retried with the same request. That retry is a cache hit only if it reaches the same worker, so send the same session key on the retry. Do not append the partial assistant output to the history before retrying: the truncated message becomes part of the prefix on every later turn and differs from what any provider cached.
Editing history
Rewriting an earlier message, re-ranking retrieved chunks, or moving a summary to the top of the prompt changes the prefix at that point. Everything after it misses. This is expected; caching is prefix-based. Append, and when you must rewrite, do it once at a compaction boundary so the new prefix caches fresh and stays stable.
TTL expiry and eviction
Anthropic's default cache lives 5 minutes; a user who reads a long response and replies six minutes later pays a cache write again. OpenAI holds 30 minutes on GPT-5.6. Morph defaults to LRU with no fixed expiry and lets you set a sliding cache_ttl up to 24h for sessions that go idle between turns. Past the TTL the prefix stops hitting entirely, and re-sending it caches it again at the normal input rate; there is no write surcharge on Morph.
FAQ
What is prompt caching?
Prompt caching reuses the key-value (KV) cache a model computed for the beginning of an earlier prompt. When a new request starts with the same tokens in the same order, the serving engine skips prefill for the matching prefix and only computes the tokens after the divergence point. The provider bills the reused tokens at a cached-input rate: 0.1x the base input price on Anthropic (0.025x on Claude Fable 5.1), OpenAI GPT-5.6, Gemini 3.x, and Moonshot Kimi K3; $0.007 vs $0.22 per 1M on DeepSeek V4 Flash off-peak; and $0.26 vs $1.25 per 1M on GLM-5.3 744B at Morph.
How much does prompt caching save?
It depends on the hit rate and the cached-to-input ratio. A 30-turn coding agent with a 20k-token system prompt and tools, growing 1,500 tokens per turn, sends 1,252,500 prompt tokens in total. At a 90% hit rate on GLM-5.3 744B at Morph the session costs $0.516 instead of $1.63, a 68% reduction. On DeepSeek V4 Flash at Morph it costs $0.056 instead of $0.160. Exact multi-turn replay pushes the hit rate to about 95%, because only the first prefill and each turn's new tokens miss.
Is prompt caching automatic?
On OpenAI (GPT-5.6 and later), Google Gemini 2.5 and newer (implicit caching), DeepSeek, Moonshot Kimi, and Morph, yes: matching prefixes are detected and billed at the cached rate with no request changes. Anthropic requires explicit cache_control breakpoints on the content blocks you want cached and charges a write surcharge of 1.25x base input for the 5-minute TTL or 2x for the 1-hour TTL. Gemini also offers explicit CachedContent objects billed per token-hour of storage.
Why is my cache hit rate zero?
The prefix changes between requests. Diff two consecutive prompts byte for byte; the first differing token ends the cacheable prefix. The usual culprits are a timestamp, request ID, or user name in the system prompt, tool definitions serialized in a different order, retrieved context inserted before the conversation instead of after it, or prompts shorter than the provider's minimum (1,024 tokens on OpenAI GPT-5.6 and Anthropic Sonnet 5, 4,096 on Gemini 3.x and Claude Haiku 4.5, about one 1k block on Morph).
Does switching models mid-conversation break the cache?
Yes. Every model has its own KV cache, so the first turn on a new model prefills the entire conversation at that model's full input rate. At turn 15 of the example session the context is 41,000 tokens: continuing on DeepSeek V4 Flash at Morph bills those tokens at the cached rate for $0.001, while moving them to GLM-5.3 744B prefills them fresh for $0.051. Route at session boundaries, hold the model once context is expensive, and escalate single turns without abandoning the cheap model's warm prefix.
What is a session key for prompt caching?
A per-conversation identifier that tells the serving layer which worker to send the request to. Caching is automatic, but a cached prefix lives in the memory of the worker that prefilled it; a follow-up that lands on a different worker re-prefills everything. On Morph, send the same value in the prompt_cache_key body field or the x-session-id header on every turn of a conversation, including retries. OpenAI's prompt_cache_key does the same job for its cache routing.
How long does a cached prompt last?
Anthropic: 5 minutes by default, 1 hour with the extended TTL, refreshed on each hit. OpenAI GPT-5.6: 30 minutes after the most recent write or reuse. DeepSeek: cleared when unused, usually within hours to days. Morph: LRU with no fixed expiry by default, or a sliding cache_ttl of 5m, 30m, 1h, 6h, or 24h set per request. Gemini explicit caches are billed per token-hour of storage for as long as you keep them.
Automatic prompt caching on every open model
No breakpoints, no write surcharge. GLM-5.3 744B at $0.26 per 1M cached input, DeepSeek V4 Flash 0731 at $0.03125, with a session key that keeps every turn on the worker that holds its prefix and a cache_ttl you set per request.
Sources
- Anthropic: Prompt caching (1.25x 5-minute write, 2x 1-hour write, 0.1x read, 0.025x on Fable 5.1; per-model minimums of 512, 1,024, and 4,096 tokens; Sonnet 5 $2 / $2.50 / $4 / $0.20)
- OpenAI: Prompt caching (enabled by default; 1,024-token minimum on GPT-5.6 and later; 0.1x cached reads; 30-minute retention; prompt_cache_key influences routing)
- OpenAI: API pricing (GPT-5.6 Terra $2.00 input, $0.20 cached input, $12.00 output per 1M)
- Google: Gemini API context caching (implicit caching on by default for 2.5 and newer; 4,096-token minimum on 3.x models; explicit CachedContent)
- Google: Gemini API pricing (Gemini 3.5 Flash $1.50 input, $0.15 cached, $1.00 per 1M tokens per hour storage; 3.1 Pro Preview $2.00 / $0.20 / $4.50 per hour)
- DeepSeek: Models and pricing (deepseek-v4-flash $0.007 cache hit, $0.22 cache miss, $0.66 output per 1M off-peak; peak double, 01:00 to 04:00 and 06:00 to 10:00 UTC weekdays)
- DeepSeek: Context caching (enabled by default; full prefix match; prompt_cache_hit_tokens and prompt_cache_miss_tokens; cleared when unused within hours to days)
- Moonshot: Kimi K3 pricing (kimi-k3 $0.30 cache hit, $3.00 cache miss, $15.00 output per 1M; 1,048,576-token context)
- Moonshot: Kimi K3 quickstart (multi-turn rule: add the complete assistant message to the next request, not content alone)
- Morph: Prompt caching (automatic prefix caching, cached rates, ~1k-token blocks, prompt_cache_key and x-session-id, cache_ttl tiers, usage.prompt_tokens_details.cached_tokens)
- Morph: Model Router (/v1/router/multimodel and /v1/router/classify, $0.005 per request, cache-breaking events, 60k-token context lock)