Originally published at kalyna.pro
If your app sends the same large system prompt, tool definitions, or document context on every request, you're paying full price to re-process those tokens every single time. Prompt caching lets Claude reuse the processed representation of a prompt prefix across requests — cache hits cost 90% less than normal input tokens. This guide covers how caching actually works, the pricing math for writes vs reads, where to place cache breakpoints, and worked cost examples for RAG apps and agents.
Prerequisites
pip install anthropic
See the Claude API Tutorial if you're new to the Messages API, and Claude API Pricing Explained for base per-model pricing.
How Prompt Caching Works
Caching works on prefixes. A request is processed top to bottom — system prompt, then tool definitions, then messages. You mark a cache breakpoint by adding "cache_control": {"type": "ephemeral"} to a content block. Everything from the start of the prompt up to and including that block is cached as a unit.
On the next request, if the prefix up to a breakpoint is byte-for-byte identical to a cached prefix, Claude reads the cached version instead of reprocessing it — you only pay full price for whatever comes after the last matching breakpoint. If anything before a breakpoint changes, that cache entry misses and gets rewritten.
- Cached prefixes expire after 5 minutes by default, refreshed on every cache hit
- An extended 1-hour TTL is available for less frequent traffic
- Each cacheable block must be at least 1024 tokens for Sonnet and Opus, or 2048 tokens for Haiku — shorter blocks aren't cached
- Up to 4 cache breakpoints per request
Pricing: Cache Writes vs Cache Reads
Using Claude Sonnet 4.6 ($3 / $15 per 1M tokens, input/output) as an example:
- Base input tokens — $3.00 / 1M
- Cache write, 5-minute TTL (default) — 1.25× base: $3.75 / 1M
- Cache write, 1-hour TTL (extended) — 2× base: $6.00 / 1M
- Cache read (cache hit) — 0.1× base, a 90% discount: $0.30 / 1M
- Output tokens — unaffected: $15.00 / 1M as usual
The same multipliers apply to every model's base price — for Haiku 4.5 ($0.25 / $1.25 per 1M) a cache read costs $0.025 / 1M; for Opus 4.7 ($15 / $75 per 1M) it costs $1.50 / 1M.
Cost Example: A RAG Chatbot
A RAG chatbot sends a 10,000-token retrieved-context block as the cached prefix, handling 100 requests/day at a steady pace.
Without caching: 100 × 10,000 × $3.00/1M = $3.00/day
With caching: first request writes the cache (10,000 × $3.75/1M = $0.0375). The remaining 99 read from cache (99 × 10,000 × $0.30/1M = $0.297). Total: ≈ $0.33/day — about an 89% reduction, compounding with every extra request.
Basic Example: Caching a System Prompt
from anthropic import Anthropic
client = Anthropic()
LARGE_SYSTEM_PROMPT = open("knowledge_base.md").read() # 8,000+ tokens
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=[
{
"type": "text",
"text": LARGE_SYSTEM_PROMPT,
"cache_control": {"type": "ephemeral"},
}
],
messages=[{"role": "user", "content": "Summarize the refund policy."}],
)
print(response.usage)
# Usage(input_tokens=12, cache_creation_input_tokens=8000, cache_read_input_tokens=0, ...)
The first call writes the cache. Send the same system prompt again within 5 minutes, and cache_read_input_tokens=8000, cache_creation_input_tokens=0 — those tokens now cost 90% less.
Caching Tool Definitions
Tool schemas count as input tokens on every call, including every step of a tool-use loop. Cache them by adding cache_control to the last tool in the list:
tools = [
{"name": "get_stock_price", "description": "...", "input_schema": {...}},
{"name": "get_exchange_rate", "description": "...", "input_schema": {...}},
{
"name": "get_current_time",
"description": "Get the current date and time in UTC.",
"input_schema": {"type": "object", "properties": {}},
"cache_control": {"type": "ephemeral"},
},
]
This caches all tool definitions as one prefix block — high leverage for agents, since tools is resent unchanged on every loop step.
Caching Long Documents
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": f"<document>{long_document}</document>",
"cache_control": {"type": "ephemeral"},
},
{
"type": "text",
"text": "What are the payment terms in section 4?",
},
],
}
],
)
Follow-up questions about the same document, sent within 5 minutes, only pay full price for the new question.
Extended TTL: 1-Hour Cache
{
"type": "text",
"text": LARGE_SYSTEM_PROMPT,
"cache_control": {"type": "ephemeral", "ttl": "1h"},
}
The 1-hour cache costs 2× base to write (vs 1.25× for 5-minute), reads are still 0.1×. It pays off once a cached prefix is reused at least twice within the hour. For traffic denser than every 5 minutes, the default TTL is usually cheaper.
Multiple Cache Breakpoints
Up to 4 breakpoints per request:
system=[
{
"type": "text",
"text": STATIC_INSTRUCTIONS, # rarely changes — shared across all users
"cache_control": {"type": "ephemeral"},
},
{
"type": "text",
"text": USER_PROFILE_CONTEXT, # changes per user
"cache_control": {"type": "ephemeral"},
},
]
Claude checks for the longest matching cached prefix. Ordering from least-to-most volatile means a change to USER_PROFILE_CONTEXT doesn't invalidate STATIC_INSTRUCTIONS.
Best Practices
- Put stable content first, volatile content last — only what comes after the last cache hit is billed at full price
- Don't cache below ~1024 tokens (2048 for Haiku) — no discount applies
- Cache growing conversation history for multi-turn chats
- Cache the
toolsarray for agents - Track
usage.cache_read_input_tokensvscache_creation_input_tokens— aim for 90%+ hit rate on steady traffic - Use 1-hour TTL only when requests are >5 min apart but reuse the prefix within an hour
Summary
- Prompt caching reuses a processed prompt prefix, marked via
cache_control: {"type": "ephemeral"} - Cache reads cost 0.1× base price; 5-min writes cost 1.25×, 1-hour writes cost 2×
- Minimum cacheable size: 1024 tokens (2048 for Haiku)
- Default TTL is 5 minutes (refreshed on hits); use
"ttl": "1h"for sparser traffic - Up to 4 breakpoints per request, ordered least-to-most volatile
- Best targets: system prompts, agent tool definitions, RAG documents, conversation history
Further reading: