A local cache and a provider prefix cache are not the same mechanism, and treating them as one is where most invalidation bugs start.
The provider layer caches the computed key-value state behind a repeated prompt prefix. The match is on the literal token sequence, so a single changed character before the cache boundary breaks the hit, as the Modular inference handbook explains. Providers then keep that entry for a fixed window. On the Claude prompt caching docs, the default lifetime is five minutes and it is refreshed at no cost each time the cached content is used, measured from the start of the request that writes or reads the entry rather than from the end of the response.
The local layer is yours. It holds the thing you actually send: a serialized system prompt, a retrieved document set, a tool manifest, a rendered context block. It is a key-value store with a TTL you pick, and it returns a full string rather than a KV state.
That difference matters for invalidation. When the provider entry expires, the next request just pays full prefill again. Nothing is wrong, it is only slower and more expensive. When your local entry goes stale, you can send an outdated document or an outdated instruction to the model, and the model will answer from it confidently.
So the local TTL governs correctness. The prefix TTL governs cost and latency. Your matrix has to respect that split.
| Property | Local cache | Provider prefix cache |
|---|---|---|
| What is stored | The serialized context you send | Computed KV state for a token prefix |
| Who controls the TTL | You | Provider policy or request parameter |
| Match rule | Your key (usually a hash or source ID) | Exact token prefix, including whitespace |
| What a stale entry causes | A wrong or outdated answer | Extra prefill cost, not a wrong answer |
| How you observe it | Your own counters | Usage fields and response headers |
| Failure to watch | Silent staleness | Low hit rate and higher bills |
The exact-match requirement is strict. vLLM prefix caching hashes each block on the tokens in the block plus the tokens in the prefix before it, and only full blocks are cached. Furiosa's prefix caching docs describe the same idea as a radix tree that reuses the longest token-exact prefix and computes only the unmatched suffix. Neither layer will forgive a moved timestamp at the top of your prompt.
That is the first decision rule: anything that varies per request must live after the cache boundary, or your prefix hit rate collapses regardless of the TTL you set.



