Cache writes cost roughly three times what reads do. Most teams don't know.
On one measured workload the median cached call that wrote cost 7.8x the median call that read — and the write is the failure case, because a write is what happens when a read was not available.
Prompt caching has two prices, and almost everyone budgets with only one of them.
A cache read — the thing everyone means by "caching" — costs 0.1x the normal input rate on most Anthropic models. A cache write, the act of filling the cache in the first place, costs 1.25x the input rate for the default 5-minute tier. Per token, a written token costs 12.5 times a read token. The write is not an implementation detail. It is the dominant term in whether caching saves you anything at all.
Here is what that looks like on real traffic. On one workload we measured in mid-August — a production agent routed through the proxy, all figures from logged calls, not estimates — the split was:
111 calls that READ from cache $0.021 – $0.034 per call
35 calls that WROTE to cache $0.140 – $0.189 per callThe median writing call cost 7.8x the median reading call. A second workload, with shorter prefixes and a higher read fraction, came in at 3.3x. Both numbers are per-call costs from one customer's traffic, so treat the ratio as a shape, not a constant — but the shape is the point. If you have ever wondered why a "cached" agent's bill did not drop the way the 0.1x multiplier promised, the answer is usually sitting in the write column.
Why writes happen when you expected reads
A write is not an error. Something has to fill the cache before anything can read it, and on a healthy workload you see a thin stream of writes — one per TTL window per distinct prefix — with everything else reading. The problem is every write beyond that baseline, because each one is a call that should have found a live cache entry and did not. Four causes account for nearly all of them.
The prefix bytes changed. Caching is an exact byte match on the front of the request. A timestamp, a session id, a reordered tool array — any of them makes this call's prefix a new string, and a new string can only write. We wrote up the most common version of this in the timestamp post, and the tool-ordering variant in reordering your tools busts your cache. The write-heavy signature of both failures is identical: hit rate near zero, write count near call count.
The TTL expired. The default cache lives five minutes. An agent that runs every twenty minutes writes on every single run and never reads — it is paying the 1.25x premium on each call for a cache nothing ever comes back for. That prefix is 25% more expensive than not caching at all. The fix is either the 1-hour tier, which costs 2x to write and changes the arithmetic, or accepting that a low-frequency agent is not a caching candidate.
The prefix crossed under the model minimum. Anthropic ignores a cache breakpoint on a prefix below the model's published minimum — silently, while still accepting the request — so a prompt that shrank below the floor keeps "caching" in your code and stops caching in reality.
Different cache scope. A cache warmed by one workspace, or on one platform, does nothing for calls arriving from another. Two services sharing a prompt template do not share a cache entry unless they share the scope the provider isolates on.
The arithmetic that decides whether caching pays
For the standard 5-minute tier, one write plus N reads of the same prefix costs 1.25 + N × 0.1 input-units, against 1 + N units for sending the prefix uncached every time. Break-even is at exactly one read: a written entry that gets read a single time before it expires has already paid for itself (1.35 vs 2.0). Everything after that is nearly free.
Which means the whole question of caching collapses to one measurable number: how many reads does each write get? Above one, you win, increasingly. At zero, you are donating a 25% premium to nobody. The ratio on the first workload above — 111 reads against 35 writes, roughly 3.2 reads per write — is a workload that wins, and still leaves money on the table: some of those 35 writes were re-writes of content that had a live entry, which is its own finding and its own post.
Why most teams don't know their ratio
Because the usage object makes it easy not to. Providers report cache_creation_input_tokens and cache_read_input_tokens as two more fields in a struct most telemetry sums into "input tokens" and forgets. The bill arrives as one number. Nothing in the default tooling ever confronts you with "this agent wrote 4,000 times and read 60" — you have to compute it, per agent, per prefix, and almost nobody does.
That is the measurement Vigil does per call: every logged call carries its write and read token counts separately, priced at their own multipliers, and the dashboard's optimise view shows the per-agent ratio directly. But you do not need Vigil to do this — you need the two fields your provider is already sending you, split out instead of summed.
What to do
Pull one day of your own usage logs and compute two numbers per agent: total cache_creation_input_tokens and total cache_read_input_tokens. If writes rival or exceed reads on any agent, that agent is paying the premium without collecting the discount — check the prefix for volatile bytes, check the call frequency against the 5-minute TTL, and check the prefix length against your model's minimum. And if you see zero in both columns on an agent you believed was cached, the breakpoint is either missing or being silently ignored, which is worse news delivered more quietly.