A B2B analytics assistant is close to the textbook case for prompt caching: the same large context — a data dictionary, last quarter's KPI definitions, a company's reporting conventions — gets sent on every single query, with only the analyst's actual question changing. Without caching, you pay full input price for that context on every request. With caching, you pay it once, then a fraction of that on every request afterward, for as long as the cache stays warm.
Setting it up correctly
1. Put the stable content first, the changing question last. Caching works on a prefix — order the request so the large, reused context comes before the analyst's specific query, and mark the end of the reused block with a cache breakpoint.
2. Use a real, current model. "Claude 3.5 Sonnet" was retired in October 2025 — the current mid-tier model is Claude Sonnet 5 (claude-sonnet-5), and prompt caching works the same way across it and the current Opus and Haiku tiers.
3. Check the usage numbers, not just your intuition. After a few requests, look at cache_read_input_tokens in the response. If it's zero, something in the "stable" part of your prompt is actually changing between calls (a generated timestamp, a re-serialized JSON blob with unstable key order) and silently busting the cache every time.
# Caching a large, reused analytics context across many analyst questions
import anthropic
client = anthropic.Anthropic()
# DATASET_CONTEXT is the large, stable block (schema, KPI defs, conventions) -
# identical on every call. The analyst's question is the only thing that varies.
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
system=[{
"type": "text",
"text": DATASET_CONTEXT,
"cache_control": {"type": "ephemeral"} # marks the end of the cached prefix
}],
messages=[{"role": "user", "content": analyst_question}],
)
print(response.usage.cache_read_input_tokens) # served from cache, ~0.1x cost
print(response.usage.cache_creation_input_tokens) # written to cache this call, ~1.25x cost
print(response.usage.input_tokens) # uncached remainder, full price
| Token type | Relative cost | When it applies |
|---|---|---|
| Cache write | ~1.25x base input price (5-min TTL) / ~2x (1-hour TTL) | The first request that writes the cached block |
| Cache read | ~0.1x base input price | Every subsequent request that reuses the same prefix |
For a B2B analytics tool fielding dozens of questions against the same underlying context, the arithmetic is straightforward: the break-even point is around two requests for the default 5-minute cache, and around three for the longer 1-hour option. Past that, every additional analyst question against the same context is a meaningfully cheaper and faster call than sending the full context from scratch each time.
Practical Challenge
Take a prompt you're already sending repeatedly with the same large context, add a cache_control breakpoint after the stable part, and run it three times in a row. Check whether cache_read_input_tokens shows up nonzero on the second and third calls.
Concept Check
cache_control breakpoint but cache_read_input_tokens stays at zero across repeated requests. What's the most likely cause?Sources & Further Reading
- Anthropic — Prompt caching documentation — official reference for cache_control, TTLs, and pricing multipliers used in this article.
AI