Ask
118
@pomodoro_pat ·

prompt caching enabled for a week and cache_read_input_tokens is still zero prompt-caching

RAG assistant, prompts average about 9,200 input tokens. I put a cache breakpoint on the system block a week ago and ran roughly 40,000 requests through it since.

cache_read_input_tokens is 0 on every single response. cache_creation_input_tokens is populated every time. The bill went up about 8%, which I assume is the cache write premium being paid forever and never redeemed. What do I actually check?

9 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @ines_marchetti · 22h ago · 2 replies

    Also check the cached region is long enough to be cacheable at all. There is a minimum prefix length below which the cache control marker is simply ignored, and you get no error and no warning — just a response with zeroes in it that looks exactly like your situation.

    If your system block alone is a few hundred tokens and the breakpoint sits right after it, that is the whole explanation. Move the breakpoint later so the cached region includes the tools and any stable context.

    47
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @pomodoro_pat · 2d ago

      System block is about 1,900 tokens so probably not my problem, but the silent-ignore behaviour is worth knowing about. Useful thing to rule out.

      14
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @visa_run_val · 3h ago · 3 replies

    Cache creation populated and cache read zero means the prefix is different on every request. It has to match byte for byte from the very first token, and it is nearly always one of these:

    • something time-varying inside the cached region. A timestamp, a request id, "today is Thursday", a session id. One field, and the entire prefix is new.
    • tool definitions in a non-deterministic order. If you build them by iterating an object or a Set, the order can shift between processes. Serialise from a fixed array.
    • retrieved chunks placed before the breakpoint, so the prefix contains the one thing that changes with every question.
    • gaps longer than the cache lifetime. The default TTL is short, so bursty overnight traffic can miss even when your average request rate looks healthy.

    Order it: system, tools, long stable context, breakpoint, then everything per-request after it.

    The fastest way to find yours: log the serialised prompt for two consecutive requests and diff them. It will be one line and you will feel silly, which is the good outcome here.

    89
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @pomodoro_pat · 3h ago

      Line 3 of the system prompt. Current time: 2026-07-24T09:12:44Z. Someone added it eight months ago so the model would know what "last week" means. Diffed two prompts and there it was in under a minute.

      31
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
    • @harlan_voss · 3h ago

      We had the identical shape of bug with the user's display name injected into the system prompt for tone. Moved it into the first user turn and hit rate went from 0 to about 94% the same afternoon. Anything per-user or per-moment belongs after the breakpoint, no exceptions.

      18
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @yaml_yuri · 3h ago · 2 replies

    The retrieved-chunks point deserves its own answer, because it is a ceiling on how much this can ever be worth for you.

    In classic top-k RAG the chunks are the majority of the prompt and they differ per question by design. So even with everything configured perfectly, the cacheable share of 9,200 tokens might be 2,700 of it. Prompt caching pays enormously for long stable context — a large system prompt, an agent loop where the conversation history grows monotonically, twenty questions asked against one document — and modestly for retrieval.

    Worth calibrating before you spend another week on it.

    29
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @visa_run_val · 13h ago

      And the fix for that ceiling is architectural rather than configuration. If the corpus for a session fits in context, put the whole document in the cached prefix and skip retrieval entirely — cheaper per question after the second one, and the answers are better because nothing got chunked badly.

      20
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @vesting_cliff · 3h ago

    Instrument this off the usage fields, not off the invoice. The invoice lags and blends every route together, so you cannot tell which one regressed.

    We track cache read tokens over total input tokens, per route, on one chart. A prompt change that quietly breaks the prefix shows up within an hour instead of at the end of the month.

    22
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @bedroomsynth · 3h ago

    We did the full caching project and clawed back 6%. Then someone cut the system prompt from 2,400 tokens to 600 by deleting instructions the model was ignoring anyway, and that was 40%. Do the boring one first, then cache what is left.

    11
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report