Skip to content

C5 · lesson 2 · 9 min read

Prompt caching

Reuse a stable prompt prefix across requests, place cache breakpoints where content stops changing, and confirm hits from the usage fields.

Ընտրեք տեքստը՝ հայերեն թարգմանությունը տեսնելու համար։Highlight text to see Armenian. Machine-assisted translation; English is the source of truth.

Official video by Anthropic on YouTube. Pressing play loads it from youtube-nocookie.com. ·open on YouTube

Many workloads send the same large block of text over and over: an on-call bot’s runbook, a long tool list, a policy document a reviewer checks every PR against. Prompt caching lets the API reuse the already processed prefix instead of reading it again. That cuts cost and time to first token. The output is the same either way.

The prefix is ordered

The cached prefix is built in a fixed order: tools → system → messages. A cache hit requires that everything up to the breakpoint is identical, byte for byte, to an earlier request.

toolssystem + runbookold turnsnew msgbreakpointbreakpointidentical prefix → cache readuncachededit a tool → tools, system and messages all miss; edit system → system and messages miss
Stable content first, changing content last. A breakpoint caches everything before it.

This gives you a simple design rule: put stable content first and changing content last. Tool definitions and the runbook go at the front. The alert payload, the user’s question and anything with a timestamp go at the end.

Placing breakpoints

There are two ways to mark what to cache:

  • Automatic caching: set a top-level cache_control: {"type": "ephemeral"}. The API puts the breakpoint on the last cacheable block and moves it forward as the conversation grows, which suits multi-turn chats.
  • Explicit breakpoints: put cache_control on individual blocks in tools, system or messages. A request can have up to 4 breakpoints, and automatic caching uses one of them.

Put a breakpoint on the last block that stays the same across the requests that should share the cache, never on the incoming question itself.

# cached_runbook.py - cache a long runbook in the system prompt
import anthropic

client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY
runbook = open("runbook.md", encoding="utf-8").read()

def ask(question: str):
    resp = client.messages.create(
        model="claude-sonnet-5-5",
        max_tokens=512,
        system=[
            {"type": "text", "text": "You are the on-call assistant for the payments platform."},
            {"type": "text", "text": runbook, "cache_control": {"type": "ephemeral"}},
        ],
        messages=[{"role": "user", "content": question}],
    )
    u = resp.usage
    total = u.cache_read_input_tokens + u.cache_creation_input_tokens + u.input_tokens
    print(f"write={u.cache_creation_input_tokens} read={u.cache_read_input_tokens} "
          f"uncached={u.input_tokens} total_input={total}")

ask("Checkout latency p99 is 4s. What do I check first?")
ask("The payments DB replica lag alert fired. Next step?")

What breaks a cache

Since the prefix is ordered, a change invalidates its own level and everything after it:

You change What misses
A tool’s name, description or schema Tools, system and messages
The system prompt (or toggling features such as citations) System and messages
tool_choice, images added or removed, thinking settings Messages

The usual mistakes are a timestamp or request ID at the top of the system prompt, tool definitions built from an unordered dictionary so their order changes, or a per-tenant line placed above the shared runbook. Each one makes every request a cache write and never a read.

Prompts below a minimum cacheable length (it depends on the model) are simply not cached, and no error is returned. If both cache fields are 0, check the length first.

Reading the usage fields

Field Meaning
cache_creation_input_tokens Tokens written to the cache this request
cache_read_input_tokens Tokens served from the cache
input_tokens Tokens after the last breakpoint only

Total input is the sum of all three. A request with a 150k-token cached runbook and a 40-token question reports input_tokens: 40. Don’t mistake that for the size of the prompt. All three still count toward the context window. Caching changes what you pay for those tokens, not whether they take up space.

There is a throughput benefit as well. For most current models, cache reads don’t count toward the input-tokens-per-minute rate limit. Only uncached input and cache writes do. A high cache hit rate therefore increases your effective throughput as well as lowering cost.

In Claude Code, caching is automatic. /usage shows a Prompt cache line with the share of input served from cache and the misses. A miss right after compaction is expected, because the conversation was rewritten.

Recap

  • Caching reuses an identical prefix built in the order tools → system → messages. Put stable content first and changing content last.
  • Use automatic caching or up to 4 explicit cache_control breakpoints, placed on the last block that stays the same.
  • A change at one level invalidates that level and every later one. Prefixes that are too short are silently not cached.
  • Total input = cache_read_input_tokens + cache_creation_input_tokens + input_tokens. Cache reads usually don’t count toward ITPM.

See it in action

a cache write, then a cache hit · illustrative session
transcript
$ python runbook_qa.py --question "how do I fail over the DB?"
usage: input_tokens=38  cache_creation_input_tokens=4812  cache_read_input_tokens=0
$ python runbook_qa.py --question "who owns the payments queue?"
usage: input_tokens=41  cache_creation_input_tokens=0  cache_read_input_tokens=4812
# same runbook prefix → read from cache on the second call

$ ./try-it.sh

Try it: cache a runbook system prompt

  1. Export ANTHROPIC_API_KEY and save the script from this lesson as cached_runbook.py. Put a long runbook (a few thousand words) in runbook.md.
  2. Run it. The first call should show cache_creation_input_tokens > 0, and the second call cache_read_input_tokens > 0.
  3. Add the current timestamp to the start of the system prompt and run it again. Watch the cache read drop to 0, then move the timestamp into the user message instead.
  4. Shrink runbook.md to a few lines and run it again. Both cache fields are 0 because the prefix is below the minimum cacheable length, and no error is raised.

Check yourself

3 questions. Original practice questions, not taken from the real exam.

  1. An on-call assistant sends the same 40k-token runbook in every request. The system prompt begins with "Current time: <timestamp>" followed by the runbook, which carries a cache_control breakpoint. The usage fields show a cache write on every request and never a read.

    1. What is the simplest fix?

  2. A response from your cached PR-review bot reports input_tokens: 85, cache_read_input_tokens: 120000, cache_creation_input_tokens: 0.

    2. How many input tokens did this request actually process, and what does that mean for the context window?

  3. Your team's agent caches its tool definitions, a long system prompt and the conversation history. Several changes are proposed for the next release.

    3. Which single change will cause cache misses at all three levels (tools, system and messages) on the next request?

Answer every question to check.