AI engineering

Anthropic Prompt Caching: Cut Cost and Latency on Repeated Context

Use Claude prompt caching to cut input cost on repeated prompts: cache_control placement, 5-minute and 1-hour TTLs, pricing maths, minimum lengths and fixes.

By EpiFive Editorial TeamReviewed/updated 9 min readHow we check articles
On this page

Anthropic prompt caching lets the Claude API reuse a prompt prefix you have already sent, so repeated context such as a long system prompt, tool definitions or a reference document is billed at a fraction of the normal input price on later requests. You turn it on by adding cache_control to the content you want cached, and you confirm it works by reading the cache fields in the response usage object.

Who this is for and what you will have

This guide is for developers whose Claude requests share a large, stable beginning: a long instruction set, a few thousand tokens of tool definitions, a document users ask many questions about, or a growing conversation. By the end you will know where to put the cache breakpoint, which TTL to choose, how to calculate whether caching saves money, how to read the usage fields, and what silently breaks a cache.

How prompt caching works

Caching covers a prefix of the request. The prefix is built in a fixed order: tools, then system, then messages. When you mark a block with cache_control, everything up to and including that block becomes eligible for the cache. On the next request, if the prefix is identical, Claude reads it from the cache instead of processing it again.

Two rules from the documentation shape everything else:

  • A cache hit needs a 100 percent identical prefix, including text and images.
  • A cache write happens only at a breakpoint, and each breakpoint looks back up to 20 blocks for an earlier write.

The only cache type is ephemeral. You can use up to 4 explicit breakpoints per request, and breakpoints themselves are free.

Prerequisites

You need an Anthropic API key, the Python SDK (pip install anthropic) and a prompt that is long enough to cache. Minimum cacheable lengths vary by model, and shorter prompts are processed without caching and without an error.

Minimum lengthModels (from the documentation)
512 tokensFable 5.1, Mythos 5.1, Opus 5.5, Opus 5, Sonnet 5.5, Fable 5, Mythos 5, Haiku 5.5
1,024 tokensOpus 4.8, Sonnet 5, Sonnet 4.6, Sonnet 4.5, Opus 4.1, Opus 4, Sonnet 4
2,048 tokensMythos Preview, Opus 4.7, Haiku 3.5
4,096 tokensOpus 4.6, Opus 4.5, Haiku 4.5

If your cached content is shorter than the minimum for your model, nothing is cached and the usage fields show zero for both cache fields.

Step 1: Add a cache breakpoint

The simplest pattern is to put the stable material in the system array and put cache_control on the last stable block. The example below caches a long policy document that every request shares.

import anthropic
 
client = anthropic.Anthropic()
 
POLICY_TEXT = open("support_policy.txt", encoding="utf-8").read()
 
def ask(question: str):
    return client.messages.create(
        model="claude-sonnet-5-5",
        max_tokens=512,
        system=[
            {
                "type": "text",
                "text": "You answer questions using only the policy below.",
            },
            {
                "type": "text",
                "text": POLICY_TEXT,
                "cache_control": {"type": "ephemeral"},
            },
        ],
        messages=[{"role": "user", "content": question}],
    )

The user question comes after the breakpoint, so it changes per request without disturbing the cached prefix.

Automatic caching

The documentation also describes automatic caching: add a single top-level cache_control field to the request and the system moves the breakpoint to the last cacheable block as a conversation grows. This suits multi-turn chat, where each turn extends the previous one.

{
  "model": "claude-sonnet-5-5",
  "max_tokens": 1024,
  "cache_control": {"type": "ephemeral"},
  "system": "You are a helpful assistant.",
  "messages": [{"role": "user", "content": "..."}]
}

Automatic caching uses one of your four breakpoint slots. If you also place an explicit cache_control on the last block with the same TTL, the automatic one becomes a no-op. A different TTL on the last block returns a 400 error, and so does a request that already has four explicit breakpoints. Check that your SDK version exposes the top-level field before relying on it; the explicit block form above works regardless.

Step 2: Choose a TTL

TTLSyntaxWrite priceNotes
5 minutes (default){"type": "ephemeral"}1.25 times base inputRefreshed at no cost on each hit
1 hour{"type": "ephemeral", "ttl": "1h"}2 times base inputCosts more to write; suits gaps longer than five minutes

The lifetime is measured from the start of the request that writes or reads the entry, so a long streaming response eats into it. When you mix TTLs in one request, 1-hour entries must come before 5-minute entries. Both TTLs have the same latency benefit, so the choice is purely about how often the prefix is reused.

Step 3: Check whether caching pays off

For models where a cache read costs 0.1 times the base input price, the arithmetic is simple. Let base input be 1 unit per prefix:

  • Two requests with no caching cost 2.0.
  • Two requests with the 5-minute cache cost 1.25 for the write plus 0.1 for the read, which is 1.35.
  • With the 1-hour cache, two requests cost 2.0 plus 0.1, which is 2.1, so you need at least two reads before it beats no caching (2.2 versus 3.0 across three requests).

The per-million-token prices below come from the pricing table on the caching page at the time of writing. Check the page before you budget, because prices and model lineups change.

ModelBase input5-minute write1-hour writeCache read
Claude Opus 5.5$4$5$8$0.20
Claude Sonnet 5.5$2$2.50$4$0.10
Claude Haiku 4.5$1$1.25$2$0.10

Note that Opus 5.5 and Sonnet 5.5 list a read multiplier of 0.05, not 0.1, so the saving is larger there. Cache writes and reads stack with other modifiers, such as the Batch API discount and long-context pricing.

Step 4: Verify with the usage fields

Print the usage object after each call.

r1 = ask("What is the refund window?")
print(r1.usage)
 
r2 = ask("Who approves exceptions?")
print(r2.usage)

The fields to watch:

  • cache_creation_input_tokens: tokens written to the cache by this request.
  • cache_read_input_tokens: tokens read from the cache.
  • input_tokens: tokens after the last breakpoint, which were not cached.
  • cache_creation: a breakdown into ephemeral_5m_input_tokens and ephemeral_1h_input_tokens.

Total input is the sum of the first three fields:

total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens

On the first call you should see a large cache_creation_input_tokens. On the second call within the TTL, cache_read_input_tokens should hold roughly the same number and input_tokens should be small. If both cache fields are zero, the prompt was not cached, usually because it fell below the minimum length.

Step 5: Avoid what invalidates the cache

Changes at one level invalidate that level and everything after it, in the order tools, system, messages.

Editing any tool definition (names, descriptions or parameters) invalidates the tools, system and messages caches. Changing tool_choice invalidates cached message blocks, while tool definitions and the system prompt stay cached. The documentation lists further settings that affect the cache, including toggling web search or citations, adding or removing images, the speed setting, and the thinking and effort configuration, so check its invalidation table before changing them mid-conversation. The practical lesson is to keep the early part of the prompt byte-identical.

Other common causes:

  • Timestamps, request IDs or per-user values placed before the breakpoint. Move them after it.
  • Reordered content. Keep the same order every time.
  • Non-deterministic JSON key ordering in tool_use blocks, which the documentation notes is common in Swift and Go.
  • Concurrent requests. They get no cache hits until the first response has started, so send one request first when you need to warm a cache.

Pre-warming a cache

You can write the cache before real traffic arrives by sending max_tokens: 0 with the breakpoint on the shared prefix. The request writes the cache and returns an empty content array with no output tokens billed. It is rejected with streaming, extended thinking, structured outputs, forced tool_choice, or inside a Message Batches request.

Step 6: Understand the rate limit benefit

Caching also raises your effective throughput. For most Claude models, only uncached input tokens count toward input tokens per minute (ITPM): input_tokens and cache_creation_input_tokens count, while cache_read_input_tokens does not. The rate limits page gives an example: with a 2,000,000 ITPM limit and an 80 percent cache hit rate, you could process 10,000,000 total input tokens per minute. Claude Haiku 3.5 is listed as an exception that also counts cache reads. This is one more reason to cache the long, shared part of agent prompts, as in Claude Tool Use in Python: Build a Simple Agent Loop Step by Step.

Troubleshooting

SymptomLikely causeFix
Both cache fields are 0Prompt below the model's minimum lengthCache more content or accept that this request is too short
Cache writes every request, no readsSomething before the breakpoint changes each timeDiff the serialised prefix between two requests; move volatile values after the breakpoint
400 error on cache_controlDifferent TTL on the last block, or more than four breakpointsUse one TTL on the last block and count breakpoints
Hits stop after a quiet periodThe 5-minute TTL expiredUse the 1-hour TTL or warm the cache before traffic
Hits stop after a prompt changePrefix no longer identicalKeep tools and system stable; change only the messages
Concurrent requests all writeNo entry exists until the first response startsSend the first request, then fan out

Checklist

  • The cached prefix is above the model's minimum length.
  • Stable content comes first, volatile values come last.
  • The breakpoint is on the last stable block, and you use at most four.
  • You chose 5 minutes or 1 hour based on how often the prefix is reused.
  • You log cache_creation_input_tokens and cache_read_input_tokens and watch the hit rate.
  • You handle rate limits as described in Handling LLM API Rate Limits: Retry, Backoff and Queues in Python.

References

Questions people ask

How much does Claude prompt caching save?

Cache reads cost 0.1 times the base input price on most models, and some newer models list 0.05 times or lower. Writing to the cache costs 1.25 times base for the 5-minute TTL and 2 times for the 1-hour TTL. With the 5-minute TTL a prefix pays for itself after a single cache read.

Why is cache_read_input_tokens always 0?

The most common cause is a prompt shorter than the model's minimum cacheable length, which is processed without caching and returns no error. Other causes are content before the breakpoint that changes on every request, such as a timestamp, or sending concurrent requests before the first response has started.

What is the difference between the 5-minute and 1-hour cache?

Both have the same latency benefit. The 5-minute cache is the default, costs 1.25 times the base input price to write and is refreshed at no cost each time it is read. The 1-hour cache is set with ttl 1h, costs 2 times to write and suits traffic where gaps between requests exceed five minutes.

Do cached tokens count toward Claude rate limits?

For most models, only uncached input tokens count toward input tokens per minute. Cache reads do not count, while input_tokens and cache_creation_input_tokens do. Claude Haiku 3.5 is listed as an exception that also counts cache reads.

Claude APIPrompt CachingPythonLLM Cost
  1. LLM Model Routing: Send Easy Requests to a Cheaper Model

    Build a simple Python router that sends each request to a small or large Claude model, then measure cost and quality against an eval set before you ship it.

    AI engineering12 min read
  2. Getting Started with LLM Evals: A Small-Team Setup with Code

    Build your first LLM eval in an afternoon: write 30 test cases in a JSONL file, grade them with simple code, add an LLM grader for tone, and track the score between prompt changes.

    AI engineering9 min read
  3. Claude Message Batches API: Cut Bulk Job Costs in Python

    Run large asynchronous Claude jobs at 50 percent of standard API prices with the Message Batches API: Python create, poll and results code, limits and fixes.

    AI engineering9 min read
  4. Claude Structured Outputs: Get Valid JSON from the API in Python

    Use output_config with a JSON schema, or messages.parse with Pydantic, to get schema-valid JSON from Claude in Python, plus the schema limits and failure cases to handle.

    AI engineering9 min read
  5. Claude Tool Use in Python: Build a Simple Agent Loop Step by Step

    Build a tool-calling agent loop with the Claude Messages API in Python: define tools, run tool_use blocks, return tool_result blocks and stop safely.

    AI engineering11 min read
  6. LLM API Timeouts, Retries and Rate Limits: A Python Reliability Guide

    Make Claude and OpenAI API calls in Python resilient: set timeouts, retry only the right errors, honor retry-after on 429, and tell spend limits from rate limits.

    AI engineering10 min read