Cut your API bill 75%: a prompt-caching tutorial
Prompt caching is the highest-ROI optimization most API users skip. This tutorial shows how it works on Anthropic, OpenAI, and Google Gemini — with pricing math, code samples, and the pitfalls that silently zero out your savings.
- Cache reads run at roughly 10% of base input pricing; on Claude Fable 5.1 cache reads cost $0.25 per million tokens against a $10/M base input price — a 97.5% discount on cache-served tokens.
- Anthropic: explicit cache_control breakpoints (up to 4), 5-minute default TTL with free refresh on read, 1-hour optional; writes cost 1.25x input (5-min) or 2x (1-hour); minimum prefix 512–4,096 tokens by model.
- OpenAI: automatic caching for any byte-identical prompt prefix of 1,024+ tokens, writes free on most current models, 5–10 minute inactivity TTL (30-minute guaranteed on GPT-5.6+).
- Google Gemini: explicit caches, 1,024-token (Flash) / 4,096-token (Pro) minimums, creation cost plus storage ($0.50–1.00/M tokens/hr), 1-hour default TTL.
- Worked example: a 10,000 requests/day agent workload at 80% hit rate on Claude Sonnet 4.6 ($3/M input, $15/M output) costs $214.50/day with caching versus $315/day without — 32% off the total bill.
If you're paying full input price on every API call, you're probably overpaying. Most production prompts resend the same material over and over — system instructions, tool definitions, retrieved documents, conversation history — and every major provider now sells you a way to stop paying full price for it. That way is prompt caching: a few lines of code, zero quality change, and 75–90% off the repeated portion of your bill.
The headline number behind this tutorial: on Anthropic's Claude Fable 5.1, cache reads now cost $0.25 per million tokens against a $10/M base input price — a 97.5% discount on any token served from cache. Across all three big APIs, cache reads run at roughly 10% of base input pricing. Here's how to capture it.
What prompt caching actually does#
Prompt caching stores the internal representation (the KV cache) of a stable prompt prefix so repeat requests skip recomputing it. Two effects: cost — repeated prefix tokens are billed at the cache-read rate (~10% of input price); and latency — time-to-first-token drops because the prefix isn't recomputed.
The catch: caching only covers stable prefixes — content that is byte-identical across requests and sits at the start of the prompt. A change mid-prefix invalidates everything after it. That single fact dictates all strategy below.
The pricing math that matters#
| Provider | Cache read (per MTok) | Cache write | Minimum prefix | TTL |
|---|---|---|---|---|
| Anthropic | 0.1× input (0.025× on Fable 5.1 / Mythos 5.1) | 1.25× input (5-min) or 2× input (1-hour) | 512–4,096 tokens by model | 5 min default (free refresh on read), 1 hr optional |
| OpenAI | ~0.1× input on current GPT-5.x rate cards | Free on most models (1.25× on GPT-5.6+) | 1,024 tokens | 5–10 min inactivity (30-min guaranteed on 5.6+) |
| Google Gemini | ~0.1× input | Creation cost + storage ($0.50–1.00/M tokens/hr for explicit) | 1,024 tokens (Flash) / 4,096 (Pro) | 1 hr default (explicit), configurable |
A few things to note. These numbers move — check the vendor pricing pages before deploying. Writes are not free on Anthropic: the first cache write costs 1.25× the base input rate, so you need roughly 3+ reads before you're in the black on a 5-minute TTL. OpenAI is the outlier in your favor: caching is automatic and writes are free on most current models, so every hit is pure savings.
A worked example#
Take an agent workload: 10,000 requests/day, each carrying a 5,000-token system prompt + tools + context, a 500-token user message, and a 1,000-token response, with an 80% cache hit rate. On Claude Sonnet 4.6 ($3/M input, $15/M output):
- Cache reads: 40M tokens × $0.30/M = $12.00
- Cache writes: 10M tokens × $3.75/M = $37.50
- Uncached input + output: $15 + $150 = $165.00
- Total: $214.50/day
Without caching, the same workload costs $315/day. That's 32% off the total bill — and the savings scale with how input-heavy your workload is. Anthropic reports up to ~45% effective savings on heavily agentic Fable 5.1 runs, entirely from the cache-read line item.
Anthropic: explicit breakpoints#
Anthropic gives you the most control — and demands the most from you. You place cache_control markers on the content blocks you want cached, and caching only happens at those breakpoints. There are two modes:
- Automatic caching (simplest): add one top-level
cache_controlfield; the breakpoint lands on the last cacheable block and moves forward as conversations grow. - Explicit breakpoints: up to 4 markers, for caching sections that change at different frequencies (e.g., rarely-changing tool definitions vs. daily-refreshed context).
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
# Option A: automatic caching — one line, breakpoint follows the conversation
cache_control={"type": "ephemeral"},
system="You are a support agent for Acme Corp. [long static instructions...]",
messages=[{"role": "user", "content": "Where is my order?"}],
)
For explicit control over multiple stable sections:
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=[
{"type": "text", "text": STATIC_SYSTEM_PROMPT,
"cache_control": {"type": "ephemeral"}}, # breakpoint 1
],
tools=[TOOLS_WITH_BREAKPOINT], # breakpoint 2
messages=[
{"role": "user", "content": [
{"type": "text", "text": STATIC_KB_CONTEXT,
"cache_control": {"type": "ephemeral"}}, # breakpoint 3
{"type": "text", "text": user_question}, # changes per request
]}
],
)
Rules that matter: put static content first and dynamic content (timestamps, user messages) after your last breakpoint, since Anthropic's hierarchy (tools → system → messages) invalidates everything after a change. Prefixes below the model's minimum (1,024 tokens for Sonnet 4.6, up to 4,096 for Haiku 4.5) are silently not cached — check cache_creation_input_tokens and cache_read_input_tokens in the response usage: if both are 0, nothing was cached. And watch the TTL math: a 5-minute TTL with one request every 10 minutes means every request pays the 1.25× write premium and never reads.
OpenAI: it's already on#
OpenAI's approach is the opposite philosophy: caching is automatic for any prompt prefix of ≥1,024 tokens that is byte-identical to a recent request. No markers, no code changes — you just keep the prefix stable:
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-5-5",
messages=[
{"role": "system", "content": STATIC_SYSTEM_PROMPT}, # identical every call → auto-cached
{"role": "system", "content": TOOL_DEFINITIONS_JSON}, # also static
{"role": "user", "content": user_message}, # the only thing that changes
],
)
usage = response.usage
print(usage.prompt_tokens_details.cached_tokens) # tokens served from cache
What to know: cache hits arrive in 128-token increments and show up in usage.prompt_tokens_details.cached_tokens — monitor it to verify your hit rate. The discount varies by model: current GPT-5.x rate cards price cached input around 0.1× (e.g., $0.50/M cached vs. $5/M input on GPT-5.5), while some older models were 0.5×. And prefix stability is the whole game: if cached_tokens reads 0 despite a static system prompt, something upstream is mutating the prefix — non-deterministic serialization, per-request content ahead of the static block — so fix ordering first.
Google Gemini: explicit caches + free implicit ones#
Gemini has two tiers, and they're easy to confuse:
- Implicit caching (automatic on Gemini 2.5+): if your prompt matches a recent request, you get the discounted read rate automatically. Same per-token discount as explicit, no storage cost — but no savings guarantee.
- Explicit context caching: you create a named
CachedContentobject holding your static content, then reference it by ID. Guaranteed, but you pay storage (~$0.50/M tokens/hour through 2026, rising toward $1.00) plus the discounted read rate.
from google import genai
from google.genai import types
client = genai.Client()
# Create the cache once for your static content
cache = client.caches.create(
model="gemini-3-7-flash",
config=types.CreateCachedContentConfig(
contents=[STATIC_REFERENCE_DOC],
system_instruction=STATIC_SYSTEM_PROMPT,
ttl="3600s",
),
)
# Reference it on every request
response = client.models.generate_content(
model="gemini-3-7-flash",
contents=user_message,
config=types.GenerateContentConfig(cached_content=cache.name),
)
print(response.usage_metadata.cached_content_token_count)
What to know: a request referencing a cache cannot carry its own system_instruction, tools, or tool_config — those must live in the CachedContent object. The cache's model and the request's model must match, and minimums are roughly 1,024 tokens (Flash) / 4,096 (Pro). Explicit caching only pays off when storage is dwarfed by read savings — it's built for large hot contexts; for small prefixes, implicit caching is the better deal.
The five pitfalls that kill your savings#
- Varying content before static content. A timestamp, request ID, or the user's message placed above your static blocks invalidates the prefix. Always: static first, dynamic last.
- Non-deterministic serialization. If your tool definitions serialize with random key order or your few-shot examples shuffle, the prefix is never byte-identical and the cache never hits. Freeze them as constants.
- TTL expiry on sparse traffic. On Anthropic, a 5-minute TTL with one request every 10 minutes means every request pays the 1.25× write premium and never reads. Match TTL to your arrival rate — or don't cache at all.
- Parallel fan-out. A cache entry only exists after the first response begins. N workers firing the same prefix in parallel all miss; only later waves benefit. Warm the cache with one request first, or stagger.
- Caching tiny prompts. Below the minimum token threshold,
cache_controlmarkers are silently ignored. A 300-token system prompt gets you nothing — pad the cached content or skip it.
Takeaway#
Prompt caching is the rare optimization with no downside to quality: identical outputs, lower latency, lower cost. The implementation differs — explicit breakpoints on Anthropic, automatic on OpenAI, explicit cache objects on Gemini — but the discipline is identical: identify what's static, put it first, keep it byte-stable, and monitor your hit rate.
Start today: on OpenAI, you may already be saving money — check cached_tokens in your usage. On Anthropic, add one top-level cache_control field to your highest-volume multi-turn endpoint. On Gemini, let implicit caching work and reach for explicit caches only for large, hot contexts. Then look at next month's bill — for most teams, this single change beats months of model-switching and prompt-trimming.
Pricing figures are per vendor documentation as of September 2026 and drift over time — verify current rates on the Anthropic, OpenAI, and Google pricing pages before deploying.