Prompt Caching Intro

Su Suriya Ravichandran Updated 10 Nov 2026
6 min read ·Lesson 124 of 200

Paying for the Same Tokens Again and Again

Many applications send almost the same input with every request. A support assistant repeats its instructions, a document-question tool resends the same document, and a chat resends its whole history on every turn. Without caching, Claude reads all of that text from the beginning each time, and you pay the full input price each time.

Prompt caching lets the API remember the processed form of a prompt's beginning, the prefix. When a later request starts with the same prefix, Claude reads it from the cache instead of processing it again. The result is lower cost and faster responses for the repeated part.

Request 1:  [ instructions | document | question A ]   → everything is processed and written to the cache
Request 2:  [ instructions | document | question B ]   → instructions and document are read from the cache
                                                         only question B is processed as new input

Caching changes what is processed, not what is answered. According to the documentation, prompt caching has no effect on the output: the response is the same as it would be without caching.


The Economics

Writing to the cache costs more than normal input, and reading from it costs much less. For Claude Sonnet 5.5, the current prices per million tokens are:

OperationMultiplier on base input priceSonnet 5.5 price per million tokens
Normal input (not cached)1×$2.00
Cache write, 5-minute TTL1.25×$2.50
Cache write, 1-hour TTL2×$4.00
Cache read (hit or refresh)0.1×$0.10

The write premium is a one-time cost, and each read saves most of the price. Lesson 126 calculates exactly when caching pays off. Two model-specific details also appear in the pricing table: cache reads on Opus 5.5 and Sonnet 5.5 are priced at 0.05× rather than 0.1×, and Claude Fable 5.1 and Claude Mythos 5.1 read at 0.025×. Check the pricing page for the model you use.


The Two Requirements

Caching has two conditions, and most surprises come from one of them:

  1. The prefix must be identical. Cache hits require 100% identical content, from the start of the prompt up to the marked block. A single changed character early in the prompt causes a miss for everything after it.
  2. The prefix must be long enough. Each model has a minimum length. According to the documentation, the minimum is 512 tokens for Claude Opus 5.5, Sonnet 5.5, and Haiku 5.5, and 1,024 or more for older models. Shorter prompts are processed without caching and without any error, so a prompt marked for caching may simply never be cached.

The second rule is easy to miss. The usage fields are the only way to tell whether caching happened (Lesson 125).


A First Look

The example below sends a long system prompt twice, marked for caching. The first request writes it to the cache, and the second reads it back.

"""cache_intro.py: the same long prefix, sent twice, with usage reported each time."""

from anthropic import Anthropic

client = Anthropic()
MODEL = "claude-opus-5-5"

# 80 numbered rules: well above the 512-token minimum for this model
GUIDELINES = "\n".join(
    f"Rule {n}: when a student asks about topic {n % 7}, explain the idea in plain words, "
    f"give one short example, and mention one common mistake to avoid."
    for n in range(1, 81)
)


def ask(question: str) -> None:
    message = client.messages.create(
        model=MODEL,
        max_tokens=300,
        system=[{"type": "text", "text": GUIDELINES, "cache_control": {"type": "ephemeral"}}],
        messages=[{"role": "user", "content": question}],
    )
    usage = message.usage
    print(f"written={usage.cache_creation_input_tokens} "
          f"read={usage.cache_read_input_tokens} "
          f"uncached={usage.input_tokens}")


if __name__ == "__main__":
    ask("What is a Python list comprehension?")
    ask("What is a Python dictionary?")

Expected output (token counts vary with the tokenizer; the pattern is the point):

written=<large number> read=0 uncached=<small number>
written=0 read=<the same large number> uncached=<small number>

How It Works

  1. The system prompt is a list of blocks, with cache_control on the single block that holds the long text. That marks everything up to and including that block as the cacheable prefix.
  2. The question is not marked, so it is the only part that changes between requests. It is processed normally, and shows up in input_tokens.
  3. The first call writes the prefix to the cache, and its cache_creation_input_tokens is large.
  4. The second call reads the same prefix, so cache_read_input_tokens is large and cache_creation_input_tokens is zero.
  5. The answers are unaffected. Only the processing of the repeated prefix changed.

Note: caching applies to the beginning of the prompt. Content that changes in the middle or the end of a prompt cannot benefit from a cache entry placed before it. Lessons 122 and 123 show how to arrange prompts for this.


Common Mistakes

Expecting Caching for Short Prompts

What happens: a short system prompt is marked with cache_control, but nothing is cached, and there is no error.

Fix: check the usage fields, and make the cached prefix longer than the model's minimum.

Including Changing Content in the Prefix

What happens: a timestamp or user name placed in the cached part makes every request different, so the cache never hits.

Fix: keep the cached prefix stable, and put changing content after it.

Assuming Caching Changes the Answer

What happens: developers worry that cached responses are stale or different.

Fix: remember that only the processing of the prefix is reused. Each answer is generated fresh.

Trusting the Cache Without Measuring It

What happens: a feature is assumed to be cheaper, but the usage fields show no reads at all.

Fix: log cache_read_input_tokens and cache_creation_input_tokens for every request.


Best Practices

  • Start with prefixes that are long and reused: instructions, documents, tool definitions.
  • Keep the prefix byte-for-byte stable across requests.
  • Measure with the usage fields, and confirm reads happen in practice.
  • Check the minimum length for your model before relying on caching.
  • Use caching where requests repeat within minutes, and consider the 1-hour TTL for less frequent use (Lesson 130).

Exercise

  1. Change one character in GUIDELINES between two calls. What does the second call report?
  2. Reduce GUIDELINES to 10 rules and run the example again. Does the second call read anything from the cache?
  3. Add a timestamp to the end of GUIDELINES that changes on every call. What happens to the reads, and why?
  4. Explain why the question is not part of the cached block.
Show answers for steps 2 and 4

Step 2: with 10 rules, the prompt is probably below the 512-token minimum for Opus 5.5, so nothing is written, and both calls report read=0 and written=0. No error appears. This is the silent behavior the documentation describes, and it is why the usage fields must be checked.

Step 4: the question is different for every request. If it were in the cached block, every request would have a different prefix, and no cache entry could ever be reused. Keeping the stable content first, and the changing content after it, is what lets the cache work.

0 Comments

Reviewed before they appear

No comments yet.

Anthropic SDK Using Python
Anthropic SDK Intro Claude API Intro SDK Requirements Install Anthropic SDK Upgrade the SDK Create an API Key Set API Keys Use Environment Variables Import Anthropic Create a Client Send Your First Message Choose a Claude Model Set Max Tokens Read a Response Print Response Text Understand Message Blocks Use System Prompts Send User Messages Set Temperature Handle Stop Reasons Messages API Intro Create Messages Use Message Roles Send Conversation History Continue a Conversation Build a Chat Loop Reset Chat History Use Multiple Turns Inspect Message IDs Read Usage Data Write Clear Prompts Set a System Prompt Add Context to Prompts Use Prompt Templates Add Examples to Prompts Request JSON Output Use XML Tags Control Response Length Improve Prompt Quality Avoid Prompt Injection Read Text Blocks Read Content Blocks Check Stop Reasons Count Input Tokens Count Output Tokens Count Tokens Before Sending Limit Output Tokens Use Stop Sequences Read Request IDs Parse API Responses Streaming Intro Stream Text Output Use Stream Events Use Stream Helpers Get Final Messages Stream Async Responses Handle Stream Errors Build a Live Chat Stream Long Responses Close Streams Safely Build a Chatbot Keep Chat History Manage Chat Sessions Add Chat Memory Build a CLI Chatbot Build a Web Chatbot Use Flask with Claude Use FastAPI with Claude Return JSON from an API Add Chat Error Messages Async SDK Intro Create an Async Client Send Async Messages Use asyncio Run Parallel Requests Stream Async Text Handle Async Errors Set Async Timeouts Close Async Clients Choose Sync or Async Tool Use Intro Define a Tool Create Tool Schemas Send Tools to Claude Read Tool Calls Run Python Tools Return Tool Results Continue After Tool Use Control Tool Choice Handle Tool Errors Use the beta_tool Decorator Create a Tool Runner Add Tool Docstrings Validate Tool Inputs Use Multiple Tools Limit Tool Calls Log Tool Activity Build a Weather Tool Build a Search Tool Build a Calculator Tool Structured Output Intro Request JSON Data Validate JSON Output Use Pydantic Models Handle Invalid JSON Extract Fields from Text Generate Typed Data Use Image URLs Send Base64 Images Read PDFs with Claude Use Output Schemas Build Data Extraction Test Structured Responses Send Image Inputs Upload Files Use File IDs Process Text Files Summarize Documents Extract Table Data Handle File Errors Read Cache Usage Reduce Repeated Input Costs Debug Cache Misses Prompt Caching Intro Enable Prompt Caching Cache System Prompts Cache Long Context Test Cache Performance Use Cache Breakpoints Cache Best Practices Message Batches Intro Create a Message Batch Set Batch IDs Check Batch Status List Message Batches Get Batch Results Process Batch Outputs Handle Failed Batch Items Use Batches for Bulk Tasks Compare Batches and Requests Handle API Errors Handle Rate Limits Retry Failed Requests Set Request Timeouts Handle Network Errors Use Exponential Backoff Build Reliable API Calls Use Extended Thinking Log API Errors Track Request IDs Paginate API Results Set Thinking Budgets Read Thinking Blocks Use Tool Search Use Web Search Tools Use Computer Tools Use Citations Use Token Counting Read Raw Responses Set Custom Headers Use Claude on AWS Bedrock Use Claude on Vertex AI Use Claude on Microsoft Foundry Configure Cloud Credentials Choose a Cloud Provider Compare API Integrations Configure Provider Clients Handle Cloud Errors Use Cloud SDK Extras Deploy Cloud Apps Protect API Keys Use a .env File Ignore Secrets in Git Validate User Input Reduce Prompt Injection Limit Tool Permissions Avoid Unsafe Tool Calls Sanitize Tool Results Set Usage Limits Review Security Logs Test SDK Functions Mock API Responses Test Error Handling Test Streaming Code Measure Token Usage Track API Costs Configure Logging Deploy with Docker Deploy a FastAPI App Monitor Production Apps Build a Claude Chatbot Build a Text Summarizer Build a Code Explainer Build a JSON Extractor Build a PDF Assistant Build a Streaming Chat App Build a Tool-Calling Agent Build a Batch Processor Build a Research Assistant Build a Claude API Dashboard
Ask about this post
AI Ask about this post

Ask questions about Prompt Caching Intro and get answers drawn from it.

Signed-in readers only.