If you run Claude in production in 2026 and have not turned on prompt caching, you are almost certainly overpaying, often by an order of magnitude. Anthropic's caching is the strongest lever on a Claude API bill. Unlike most "optimization tricks" it is transparent, deterministic and part of the official SDK. This post covers what prompt caching really is, the pricing math, the patterns where it pays, and the pitfalls teams hit in the first month after rollout.
What prompt caching is
Prompt caching lets you mark prefix parts of a request as cacheable. On the first call, Anthropic stores the model's internal representation of that prefix on its infrastructure. Any later call within a short TTL (5 minutes by default, refreshed on every hit) gets the same prefix from the cache, and the model does not have to encode it again.
You switch it on by adding a cache_control breakpoint to a content block. Every block at or before that breakpoint becomes part of the cache key. A request can carry up to four breakpoints, so you can build the cache in layers: a stable system prompt first, then stable tool definitions, then the moving conversation history.
The cache is scoped to the organization and to the exact prefix. Change a single token in the cached prefix and the entry is invalidated. That is the right behavior, since you never get stale context, but it is also the most common reason hit rates come in lower than expected.
The pricing math
Caching is not free. Anthropic bills the same input token at three rates:
- Standard input: 1.0× the model's listed input price.
- Cache write: 1.25× the input price (a 25% premium for filling the cache).
- Cache read: 0.1× the input price (10% of the listed rate on a hit).
The break-even for any cached prefix: one read at 0.1× plus the write at 1.25× beats two cold calls at 1.0× each after two reuses. From the third hit on, every call on that prefix is nearly free next to an uncached baseline.
Take a 20,000-token system prompt on Sonnet 4.6 at roughly $3 per 1M input tokens:
- Cold call: 20,000 × $3 / 1M = $0.060 per call.
- Cache write: 20,000 × $0.50 / 1M = $0.01 (once per TTL).
- Cache read: 20,000 × $0.05 / 1M = $0.001 per call.
Ten cached reads inside a 5-minute window cost $0.075 + 9 × $0.006 = $0.129, while the same ten calls without caching cost 10 × $0.060 = $0.600. That is a 78% reduction at ten reuses. As repeats get denser, the ceiling approaches the theoretical 90%.
Where caching pays off
Four patterns reliably pay off in production:
- Long system prompts. Anything beyond a couple of thousand tokens (detailed personas, formatting rules, brand voice, guidelines) is worth caching. A system prompt is identical across requests by definition.
- RAG with a stable knowledge base. If a fixed document corpus (product docs, policies, schemas) is baked into the prompt, cache it. The variable user queries go after the breakpoint.
- Agent tool definitions. The JSON schemas of functions and tools for a non-trivial agent easily pass 10K tokens, and they barely change between calls. Cache them.
- Multi-turn assistants with long history. Cache everything up to the last fully stable turn. Each new user message lengthens the prefix, and the earlier history is reused.
Code: Python and TypeScript through codexkey
codexkey serves Claude through an OpenAI-compatible endpoint, and prompt caching passes through transparently: no extra configuration, no proprietary headers, no rewrite. You set cache_control exactly as you would against Anthropic's native API.
from openai import OpenAI
client = OpenAI(
api_key="YOUR_CODEXKEY_KEY",
base_url="https://api.codexkey.online/v1",
)
SYSTEM_PROMPT = open("system_prompt.txt").read() # ~20K tokens
response = client.chat.completions.create(
model="claude-sonnet-5",
messages=[
{
"role": "system",
"content": [
{
"type": "text",
"text": SYSTEM_PROMPT,
"cache_control": {"type": "ephemeral"},
}
],
},
{"role": "user", "content": "Summarize the latest sales report."},
],
)
usage = response.usage
print(usage.cache_creation_input_tokens, usage.cache_read_input_tokens)
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.CODEXKEY_KEY,
baseURL: "https://api.codexkey.online/v1",
});
const response = await client.chat.completions.create({
model: "claude-sonnet-5",
messages: [
{
role: "system",
content: [
{
type: "text",
text: SYSTEM_PROMPT,
cache_control: { type: "ephemeral" },
},
],
},
{ role: "user", content: "Summarize the latest sales report." },
],
});
console.log(response.usage);
The usage object reports cache_creation_input_tokens and cache_read_input_tokens separately. That is how you confirm the cache is actually firing, so log both in production from day one.
Real production numbers
A customer running an internal support agent on codexkey's gateway moved from a 22,000-token system prompt with no caching to the same prompt behind a single cache_control breakpoint. Before caching, the system segment alone cost roughly $1,980 a month at ~30 calls an hour. After the change, with the prefix hitting 14 times on average per 5-minute window, the same line item fell to $215 a month. That is an 89% reduction, with no change to model output or quality. Tool definitions cached behind a second breakpoint trimmed about another $140 a month. In total, the agent's Claude bill dropped from roughly $2,400 a month to under $400.
That ratio is typical. Any workload with a stable prefix and at least a handful of calls per 5-minute window gets 70-90% savings on input once the cache is set up correctly.
Pitfalls
A few things catch teams on the first rollout:
- The 5-minute TTL slides; it is not fixed. Every hit extends it. But if traffic goes quiet for a full 5 minutes, the next call pays the 1.25× write again. On infrequent workloads this quietly erases the savings, so measure the distribution of gaps between requests.
- Four breakpoints is a hard limit. Lay them out in layers: system, then tools, then static context, then recent history. Do not spend breakpoints on parts that always change together.
- Any prefix change invalidates the cache. One edit to the system prompt, even a space, wipes the entry. Treat cached prefixes as immutable build artifacts and version them explicitly.
- Minimum block size. Very small cached blocks (under ~1K tokens on most models) are not cached at all, and the SDK skips them silently. There is no point caching trivial content.
When not to cache
Caching is a poor fit in a few cases:
- Single-shot calls. If the prompt will not be reused within 5 minutes, you pay the 1.25× write premium for nothing.
- Short prompts. Below the per-block minimum, caching does nothing.
- Highly variable system text. When per-user data is templated into what looks like a system prompt, every call becomes a cold write. Move the variable part below the breakpoint, or cache only the stable shell and accept that the personalized layer pays full price.
codexkey and caching
codexkey passes prompt caching through to Anthropic transparently: the same breakpoints, the same TTL, the same usage accounting in the response. There is no proprietary "caching mode" to switch on, and our write and read multipliers match Anthropic's rates exactly. If you already cache directly against Anthropic, switching base_url to https://api.codexkey.online/v1 keeps all the savings you have today.
If caching is not enabled yet, enable it this week. It is the best-value change you will make to your Claude workload all year.