Reduce Repeated Input Costs

Su Suriya Ravichandran Updated 10 Nov 2026
7 min read ·Lesson 122 of 200

Caching Is Not Automatically Cheaper

Lessons 121–125 showed that cache reads cost a fraction of normal input. That is only half of the economics. A cache write costs more than normal input, and a cache entry that expires before it is read has been paid for and never used. Caching saves money only when the same prefix is read enough times to pay back its write.

This lesson calculates that break-even point, shows how request timing decides whether caching helps, and lists the design choices that reduce repeated input cost in general.


The Break-Even Point

Let the base input price be 1. A prefix written once costs the write multiple w, and each later read costs the read multiple r. Without caching, each request costs 1 for that prefix.

After the write, with n reads:

cost with caching    = w + n × r
cost without caching = 1 + n × 1

Caching is cheaper when w + n × r < 1 + n, which rearranges to:

n > (w − 1) / (1 − r)

For the current multipliers, this gives:

SettingWrite wRead rReads needed to break even
5-minute TTL, Sonnet 5.51.250.101
5-minute TTL, Opus 5.51.250.051
1-hour TTL, Sonnet 5.52.000.102

The 5-minute cache pays back after a single reuse. The 1-hour cache needs two reuses, because its write costs twice the base price.


Timing Decides the Outcome

The break-even calculation assumes the cache stays alive between reads. Its lifetime is 5 minutes by default, or 1 hour with the extended TTL, and each read refreshes it (Lesson 130 covers the details). That creates three situations:

PatternWhat happensResult
Requests arrive more often than the TTLOne write, then readsCaching is much cheaper
Requests arrive after the TTL has expiredA write on almost every requestCaching is more expensive than no caching
Requests are spaced between 5 minutes and 1 hour apartUse the 1-hour TTLThe 1-hour cache keeps the entry alive

The second row is the costly mistake. A 5-minute cache on a feature used every 10 minutes writes on every request, paying the 1.25× premium each time for nothing.

The example below makes this concrete.


Practical Example: Comparing Caching Strategies

This script estimates the input cost of 100 requests that share a 50,000-token prefix, under four scenarios. Each scenario is simulated request by request, so the write and read logic follows the TTL rules.

"""cache_economics.py: when caching saves money, and when it costs more."""

import math

BASE_PRICE = 2.00            # USD per million tokens (Sonnet 5.5)
REQUESTS = 100
PREFIX_TOKENS = 50_000


def breakeven_reads(write_multiple: float, read_multiple: float) -> int:
    """Smallest number of reads for which caching costs less than not caching."""
    return math.floor((write_multiple - 1) / (1 - read_multiple)) + 1


def scenario_cost(gap_minutes: float, ttl_minutes: float, write_multiple: float,
                  read_multiple: float) -> float:
    """Total prefix cost in USD, simulating one request after another."""
    total_tokens_cost = 0.0
    cache_alive = False
    for _ in range(REQUESTS):
        if not cache_alive or gap_minutes > ttl_minutes:
            total_tokens_cost += PREFIX_TOKENS * BASE_PRICE * write_multiple
            cache_alive = True
        else:
            total_tokens_cost += PREFIX_TOKENS * BASE_PRICE * read_multiple
    return total_tokens_cost / 1_000_000


if __name__ == "__main__":
    print(f"Break-even reads, 5-minute TTL: {breakeven_reads(1.25, 0.10)}")
    print(f"Break-even reads, 1-hour TTL: {breakeven_reads(2.00, 0.10)}")

    no_cache = REQUESTS * PREFIX_TOKENS * BASE_PRICE / 1_000_000
    print(f"no caching: ${no_cache:.3f}")
    print(f"5-minute TTL, a request every minute: "
          f"${scenario_cost(1, 5, 1.25, 0.10):.3f}")
    print(f"5-minute TTL, a request every 10 minutes: "
          f"${scenario_cost(10, 5, 1.25, 0.10):.3f}")
    print(f"1-hour TTL, a request every 10 minutes: "
          f"${scenario_cost(10, 60, 2.00, 0.10):.3f}")

Output:

Break-even reads, 5-minute TTL: 1
Break-even reads, 1-hour TTL: 2
no caching: $10.000
5-minute TTL, a request every minute: $0.620
5-minute TTL, a request every 10 minutes: $12.500
1-hour TTL, a request every 10 minutes: $0.695

How It Works

  1. breakeven_reads() solves the inequality from the previous section. The floor(...) + 1 gives the smallest whole number of reads that is strictly greater than the threshold.
  2. scenario_cost() simulates each request. A request writes the prefix if the cache is not alive, or if the gap since the last request is longer than the TTL. Otherwise it reads the prefix.
  3. The 5-minute cache with requests every minute writes once and reads 99 times: $0.125 for the write, plus $0.495 for the reads, which is $0.62. Caching saves about 94% of the $10.00 baseline.
  4. The 5-minute cache with requests every 10 minutes writes on every request, because each gap exceeds the TTL. That is 100 writes at $0.125 each, $12.50 in total: more than the $10.00 without caching.
  5. The 1-hour cache with requests every 10 minutes writes once at the 2× price, then reads 99 times. It costs $0.695, close to the frequent-request case, and far below the mistake in step 4.

Note: the simulation ignores the small uncached question in each request, which is the same in every scenario. It also assumes steady prices and gaps. Real traffic is irregular, so measure the hit rate in production (Lesson 125).


Other Ways to Reduce Repeated Input

Caching is only one lever. Several design choices reduce the input that must be sent at all:

TechniqueHow it reduces cost
Keep the prefix stableMore reads and fewer writes (Lessons 121–123)
Put changing content lastThe stable part stays cacheable
Send only relevant toolsFewer tool definitions in every request (Lesson 84)
Trim old conversation turnsLess history to resend (Lesson 24)
Retrieve only relevant passagesSmaller documents per request (Lesson 33)
Use the Batch API for non-urgent workA discount on batch processing (Lessons 131–140)
Choose the smallest adequate modelLower base prices for simple tasks (Lesson 12)

Caching makes repeated input cheap, but output tokens are not reduced by caching. Output is typically priced several times higher than input, so keeping answers concise (Lessons 38 and 47) often matters as much as caching.


Common Mistakes

Caching Everything

What happens: writes are paid for on content that is never read again.

Fix: cache prefixes that are reused, and leave one-off content uncached.

Using the 5-Minute TTL for Infrequent Requests

What happens: every request writes, and costs more than no caching at all.

Fix: measure the gap between requests, and use the 1-hour TTL when gaps fall between 5 and 60 minutes.

Ignoring Break-Even Reads

What happens: a feature with one or two requests per prefix is cached, and the write premium is never recovered.

Fix: estimate reads per prefix before turning caching on.

Optimizing Input and Forgetting Output

What happens: input costs fall, but long answers dominate the bill.

Fix: budget output tokens separately (Lesson 47).


Best Practices

  • Estimate reads per prefix before enabling caching.
  • Match the TTL to request spacing: 5 minutes for frequent traffic, 1 hour for spaced traffic.
  • Keep prefixes stable and dynamic content last.
  • Send only the tools and history a request needs.
  • Measure hit rates and compare them with the break-even estimate.
  • Budget output tokens separately from input.

Exercise

  1. Change the gap in the 5-minute scenario to 4 minutes. Does the cost change from the one-minute case? Why?
  2. Change REQUESTS to 2, and compare caching with no caching. Which is cheaper, and by how much?
  3. Compute the break-even number of reads for a write multiple of 1.25 and a read multiple of 0.025 (Fable 5.1). Is the answer different from Opus 5.5?
  4. Explain why an application that sends one request per user per session might gain nothing from the 5-minute cache, and might lose money.
Show answers for steps 1 and 2

Step 1: no change. A gap of 4 minutes is shorter than the 5-minute TTL, so the cache stays alive, and each request reads the prefix after the first write. Only gaps longer than the TTL cause writes. This is why the TTL, not the average request rate, decides the outcome.

Step 2: with two requests, no caching costs $0.200 (2 × 50,000 tokens at $2.00 per million). Caching costs a write of $0.125 plus one read of $0.005, which is $0.130. Caching is cheaper by $0.070, about 35%. The saving is smaller than in the 100-request case, because the write premium is spread over fewer reads.

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 Reduce Repeated Input Costs and get answers drawn from it.

Signed-in readers only.