Does compressing your context break prefix caching savings
Shortening a prompt looks like a saving until you check what it did to your cache hit rate.
Yes, in most agent workloads it does, and the loss is usually bigger than the saving. Prompt caching on Anthropic and on the other major providers is a prefix match: the provider hashes your request from the first byte forward and reuses the longest identical run it has already processed. Compression edits bytes near the front of that run. Every token after the edit point becomes a cache miss, so you pay full input price on the whole remainder, plus a cache-write premium to store the new version.
The short version of the arithmetic: a cache read on Anthropic costs roughly 0.1x the base input price, and a cache write costs 1.25x for the five-minute TTL or 2x for the one-hour TTL. If compression cuts your prompt by 30 percent but converts a cache read into a full-price miss, you have traded a 0.1x line item for a 0.7x one. That is a seven-fold increase on the compressed prompt in exchange for removing 30 percent of the tokens. The compression has to be enormous, or the cache hit rate has to be near zero already, for the trade to come out ahead.
What the cache is actually matching on
The rule I keep coming back to is that the cache key is derived from the exact rendered bytes up to each breakpoint, and the render order is tools, then system, then messages. Tools sit at position zero. That ordering explains almost every surprising cache miss I have looked at.
Anthropic publishes the invalidation hierarchy, and it is worth knowing precisely because it tells you which edits are cheap. Changing tool definitions or switching models invalidates everything, including the message history. Changing the system prompt keeps the tools cache but drops system and messages. Changing tool_choice, toggling thinking, or adding an image keeps tools and system and only affects the message tier. So flipping thinking on and off mid-run is close to free. Adding one tool halfway through a session is not.
There is also a minimum. A prefix shorter than the model floor silently will not cache at all, and that floor is not monotonic across generations: 512 tokens on Claude Opus 5, 1024 on Opus 4.8 and Sonnet 4.5, 4096 on Opus 4.6 and Haiku 4.5. Aggressive compression on a smaller model can push a prompt under the floor. You then get no cache entry, no error, and a cache_creation_input_tokens of zero.
Why compression is structurally a prefix edit
Compression schemes almost always operate on the oldest content, because that is where the redundancy is. Summarising turns 1 through 20 into a paragraph rewrites the beginning of the message array. Dropping stale tool results renumbers what follows them. Rewriting the system prompt to be terser changes byte one of the system block. In each case the edit lands upstream of everything you were successfully reusing.
- Summarising early conversation turns: rewrites the front of the message array, so the entire remaining history re-enters at full price.
- Trimming or de-duplicating the system prompt: invalidates system and every message after it, while leaving only the tools tier intact.
- Reordering or pruning tool definitions to save tokens: worst case, since tools render first and take the whole cache with them.
- Non-deterministic serialisation, such as JSON dumped without sorted keys or a tool list built from a set: a compression pass that reserialises can flip byte order without changing semantics, and the cache cannot tell the difference.
- Interpolating a token count or a remaining-budget figure into the system prompt as part of a compression policy: a per-request value at the front of the prefix means nothing behind it ever caches.
When compressing is still the right call
Compression is not a mistake in itself. It is a mistake when applied to a prefix that was already being reused. The distinction I use is whether the content is stable or volatile, and whether the run is long enough for the cache to have paid for itself.
Break-even on a five-minute TTL is two requests: one write at 1.25x plus one read at 0.1x is 1.35x, against 2x if you had paid full price twice. On the one-hour TTL you need three requests, because the write costs 2x. Below that threshold, caching was never earning anything and compressing costs you nothing in cache terms. Above it, and especially in a coding agent where the same repository context gets replayed across dozens of turns, the cache is doing the heavy lifting and compression is fighting it.
The other case where compression clearly wins is when you are about to blow the context window. A miss costs money. An overflow costs the whole run. If the choice is compress or fail, compress. That is also why Anthropic separates the two mechanisms: context editing clears old tool results and thinking blocks outright, while compaction summarises server-side and hands back a block you must pass forward on the next request. Compaction fires near a threshold rather than continuously, which keeps the cache intact for the long stable stretch in between.
Compression is a fixed discount on tokens you send once. Caching is a recurring discount on tokens you send hundreds of times. In an agent loop, the recurring one is worth more.
How to tell which one you are getting
Every response carries the answer. usage.cache_read_input_tokens is what you paid 0.1x for, usage.cache_creation_input_tokens is what you paid the write premium for, and usage.input_tokens is the uncached remainder at full price. Total prompt size is the sum of all three, which trips people up when they look at a four-thousand-token input_tokens figure after an hour-long session and assume something is broken.
If cache_read_input_tokens is zero across repeated requests that should share a prefix, something upstream is changing. Diff the rendered bytes of two consecutive requests and the culprit is usually visible in the first few hundred characters. Two other things worth knowing: a breakpoint only looks back about 20 content blocks to find a prior entry, so a single turn that appends more than that can miss even when nothing changed, and a cache entry is not readable until the first response begins streaming, so fanning out N identical requests in parallel means all N pay full price.
Where Probe0 sits in this
I deliberately did not build a compression module into Probe0. It is a local proxy that every coding agent CLI on the machine routes through, and rewriting prompts in transit is exactly the operation that would quietly wreck the caching those agents already get for free. The modules that are there work on request identity instead of request content: Exact Cache stores responses on local disk and never touches the network, Semantic Cache matches against a local vector index behind a strict similarity floor and refuses to match anything carrying tool calls, and Request Coalescing collapses simultaneous identical calls into one upstream request rather than paying for both.
The part that matters for this question is Recording. Probe0 keeps a full local ledger of every request with the model, token counts, real cost, latency, and which process made the call. Because the cost figure is the real one, a cache regression shows up as a step change in cost per turn on an otherwise unchanged workload, attributable to the specific agent that caused it. That is how you settle an argument about whether a prompt change helped, rather than reasoning about it from first principles.
Honest limits: Probe0 is macOS only and in private beta, it is a single-developer tool rather than a team gateway, and its provider coverage is whatever coding agents actually call rather than a hundred-plus catalogue. It also cannot see inside a provider-side compaction decision. What it can do is tell you, per call and per process, what your prompt strategy is costing in practice.