IAnswerable

Cut LLM Costs with Prompt Caching

19 Dec 2025

Prompt caching charges you less for input tokens you’ve sent before. It sounds automatic. It isn’t — the request has to be shaped right or it never hits.

How it actually works

When you send a request, the provider can cache the token prefix — the beginning portion of your prompt — and reuse that cached computation on a later request if the prefix matches exactly. “Exactly” is the operative word: even a single changed character upstream of the cache boundary invalidates it for everything after that point.

Cache hits typically cost a fraction of normal input token pricing — for both OpenAI and Anthropic, cached input tokens run around 90% cheaper than fresh ones, with a modest write cost the first time a prefix is cached. The saving only shows up on the second and later requests that reuse that prefix.

As two requests over time:

sequenceDiagram
    participant App
    participant API
    App->>API: Request 1 - static prefix plus question A
    API-->>App: Full price - prefix now cached
    App->>API: Request 2 - same static prefix plus question B
    API-->>App: Cache hit on prefix - about 90% cheaper
  

The request shape that makes it hit

Caching works on a shared, unchanging prefix. That means:

A prompt structured as [static system prompt] + [static tool schema] + [static long document] + [changing user message] caches everything up to the user message. A prompt structured as [system prompt with today's date] + [document] + [user message] caches nothing, because the date invalidates the prefix on every single request.

Anthropic vs OpenAI, practically

Anthropic’s API requires you to explicitly mark cache breakpoints with cache_control on a content block — it’s opt-in per prompt. OpenAI’s caching is automatic for prompts over roughly 1024 tokens and requires no extra parameter, but you still only benefit if your prefix is actually stable across calls; automatic doesn’t mean guaranteed. Either way, the discipline is the same: structure static-before-variable and don’t put anything that changes above content you want cached.

# Anthropic — mark the reusable prefix explicitly
messages = [{
    "role": "user",
    "content": [
        {"type": "text", "text": long_reference_doc, "cache_control": {"type": "ephemeral"}},
        {"type": "text", "text": user_question},
    ]
}]

Where this pays off the most

The gotcha

Caches expire — typically after a few minutes of inactivity, sometimes longer for providers that offer an extended cache tier at a higher write cost. A low-traffic endpoint that gets one request every ten minutes will rarely see a cache hit no matter how well-structured the prompt is, because the cache has already cooled by the time the next request arrives. Caching earns you the most on high-frequency, shared-prefix traffic — check your actual request rate on an endpoint before assuming caching will move its bill.