Prompt Caching Best Practices
A set of numbered, actionable practices for getting reliable, ongoing value out of Claude prompt caching - covering where to place breakpoints, how to choose a TTL, and how to avoid the silent misses that quietly erase the savings.
How to Use This List
- Treat these as defaults, not absolute rules - deviate deliberately when your workload has a genuine reason to.
- Group A covers breakpoint placement, Group B covers TTL and cost decisions, Group C covers avoiding silent misses, and Group D covers monitoring and verification.
- Revisit this list whenever you add a new field to a system prompt or tool schema, since that's the most common point where a previously-healthy setup regresses.
- Pair these practices with the deeper explainer and how-to pages linked in Related for the reasoning behind each one.
A - Breakpoint Placement
- Order content by stability, not by convenience. Put the most stable content (tool schemas, long reference documents, system instructions) first, and the most volatile content (the live user question, a timestamp, a session ID) last, after any breakpoint.
- Remember the fixed request order: tools, then system, then messages. A breakpoint's coverage is determined by this order regardless of how you arrange keyword arguments in your Python call.
- Use two breakpoints when tools and system prompt change at different rates. One breakpoint on the last tool definition and a second on the system prompt lets a system-prompt edit avoid invalidating a stable tool catalog, and vice versa.
- Never put cache_control on a bare string system prompt.
cache_controlrequires the list-of-content-blocks form ofsystem; a plain string has nowhere to attach it. - In multi-turn agent loops, move the breakpoint forward every turn. Place it on the last message of the growing conversation history, and strip it from earlier messages, so the cache keeps covering "everything settled so far."
B - TTL and Cost Decisions
- Default to the 5-minute TTL unless you have a specific reason for 1 hour. It has a lower write-cost multiplier and fits the majority of interactive, bursty workloads.
- Use the 1-hour TTL for sessions with real gaps between calls. Long-running agent sessions, human-in-the-loop review, or infrequent batch jobs spread over an hour benefit from not repeatedly eating the write cost.
- Remember both TTLs are ephemeral and refresh on every hit. A steady stream of requests within the window keeps an entry alive well past its nominal TTL - you don't need to "keep it warm" manually.
- Weigh write cost against expected read count before committing to a TTL. A prefix reused only once or twice rarely recoups either TTL's write cost; a prefix reused dozens of times almost always does.
- Verify pricing assumptions against current docs, not memory. Cache write and read multipliers change independently of model releases - confirm exact numbers at platform.claude.com/docs before budgeting a workload.
C - Avoiding Silent Misses
- Never embed a timestamp, UUID, or request ID ahead of a breakpoint. These are the most common silent invalidators - move anything per-request into
messages, after the breakpoint, instead. - Serialize JSON and dict content deterministically. Always pass
sort_keys=True(or an equivalent fixed key order) for any dict that lands inside a cached prompt segment. - Build cached content from one shared function, not scattered inline literals. Centralizing system prompt and tool schema construction prevents small, accidental differences from creeping in between call sites.
- Audit third-party and framework-generated prompt content too. A tool schema builder or prompt template library can embed volatile content just as easily as your own code - check the final serialized payload, not just what you wrote by hand.
- Treat a deliberate cache miss (e.g. after trimming conversation history) as expected, not a bug. Budget for the one-time rewrite cost rather than trying to avoid it entirely when history genuinely needs to change.
D - Monitoring and Verification
- Check usage.cache_read_input_tokens and cache_creation_input_tokens on every response, not just during setup. Caching fails silently - a miss never raises an error - so ongoing monitoring is the only way to catch a regression in production.
- Test with at least two consecutive calls before concluding caching is broken. The very first call to any prefix is always a write, never a hit - that's expected, not a failure.
- Use the cache diagnostics beta for targeted investigation of a confirmed miss. Passing
diagnostics.previous_message_idgets you acache_miss_reasondirectly from the API instead of requiring a manual diff. - Tag cache metrics by endpoint or prompt, not just in aggregate. A drop in overall hit rate can hide the fact that only one specific prefix started missing; per-prompt tagging isolates the actual regression.
- Diff two supposedly-identical prefixes programmatically when investigating, never by eye. A single differing character in a multi-thousand-token prompt is effectively invisible to manual inspection.
FAQs
What's the single most common cause of prompt caching not working?
A silent invalidator ahead of the breakpoint - most often a timestamp, UUID, or non-deterministically serialized JSON object embedded in the system prompt or tool schema.
Should I always use the 1-hour TTL to be safe?
No - default to the 5-minute TTL and only reach for the 1-hour option when your workload genuinely has gaps between calls longer than a few minutes.
Is it a bug if my very first request to a new prompt shows zero cache_read_input_tokens?
No, that's expected - the first call to any prefix is always a cache write, never a hit. You need at least two calls sharing the same prefix to see a read.
Do I need to keep moving the breakpoint in a multi-turn agent conversation?
Yes - a fixed breakpoint from turn one leaves later turns' growing history uncovered. Move the breakpoint to the latest message each turn and strip it from earlier messages.
How many cache_control breakpoints should a typical request have?
Usually one or two: one on the system prompt (and optionally tools separately), plus a second, moving breakpoint on the latest message in a multi-turn conversation.
What's the fastest way to confirm caching is actually working before shipping?
Send the exact same request twice in a row and check that the second response's usage.cache_read_input_tokens is nonzero. If it isn't, something in the prefix isn't stable between calls.
Does trimming conversation history for context management break caching?
Yes, it causes a cache miss on that turn since the prefix's bytes changed - that's expected and worth budgeting for, not a sign of a broken setup.
Should third-party prompt templates be audited for cache safety too?
Yes - a framework's tool schema generator or prompt template can embed volatile content (a generated timestamp, a random example ID) just as easily as hand-written code.
How do I catch a caching regression before it shows up as a cost spike?
Log usage.cache_read_input_tokens and cache_creation_input_tokens on every request in production, tagged by endpoint, so a drop in hit rate is visible immediately rather than discovered later in a bill.
What should I do once I've confirmed a cache miss but don't know why?
Use the cache diagnostics beta (diagnostics.previous_message_id) to get a cache_miss_reason directly, or fall back to a programmatic byte diff between the two supposedly-identical prefixes.
Related
- How Prompt Caching's Prefix Match Actually Works - the mechanism behind every practice on this list.
- Placing cache_control Breakpoints on System Prompts and Tools - the full detail behind Group A.
- Debugging Silent Cache Invalidators in Long Prompts - the full detail behind Group C.
- Verifying Cache Hits with cache_read_input_tokens - the full detail behind Group D.
Stack versions: Written against the Claude model lineup current as of ~June 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (the default), and Claude Haiku 4.5 - and the official
anthropicPython SDK (latest 0.x release). Model names, SDK versions, and pricing move quickly - verify current specifics at platform.claude.com/docs before relying on them.