[BUG] Cache-read is 96% of token volume (118x output); fan-out multiplies turns with no pre-execution projection — Max 20x drained in <48h
Status Open
Reported on v2.1.259
Maintainer reply None cached
Activity 0 comments · opened Sep 3, 2026
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
### Summary
On a Max 20x plan I consumed 80% of my weekly allowance in under 48 hours of use. I parsed my own
transcripts to find out where it went, and the answer was not where I expected: **95.95% of my token
volume is cache reads** — context re-sent on every turn — against **0.81% output**, a ratio of
**118x**. The average turn carries **~165,000 tokens of re-read context**.
That means consumption tracks the **number of turns**, not the cost of each one. And the thing that
multiplies turns — subagent fan-out — is projected and bounded nowhere before it runs.
I am filing this as a cost/observability report, not a request about my account.
### Environment
- Claude Code `2.1.259`, Linux (Arch), single user, single machine
- Max 20x (upgraded mid-cycle from 5x in August)
- Aggregated from `~/.claude/projects/**/*.jsonl` — `usage` counters only, no message content
### Method (this matters — two earlier attempts got it wrong)
Transcripts contain **streaming partials**: the same `message.id` appears on several lines. Measured
here: **42,815 of 49,078 distinct ids (87.2%) repeat**, and **31,620 have a larger `output_tokens`
on a later line, while zero have a smaller one**. `cache_read_input_tokens` is **identical** across
occurrences of the same id.
So:
- summing **line by line double-counts**;
- de-duplicating by taking the **first** occurrence **under-counts output by ~2.5x**.
**The correct aggregation is one row per `message.id`, taking the maximum.** All figures below use
that, over **2,567 files**.
There is a wrinkle specific to this data that cost me a wrong number before I caught it: **in the
main conversation loop the final `usage` is what gets written** — output grows on a later line in
**0 of 9,157** repeated ids — **whereas in subagent/workflow transcripts it does so in 31,129 of
32,860 (94.7%)**. A de-duplication control run against only the main-loop files therefore *passes
truthfully* while having excluded exactly the records under investigation. If anyone else measures
this, **state how many files your scan covered** — that single line is the guard.
### The numbers
| counter | tokens | share of volume |
|---|---:|---:|
| **cache read** | **8,127,483,371** | **95.95%** |
| cache creation | 274,301,317 | 3.24% |
| **output** | **68,738,435** | **0.81%** |
| input (uncached) | 271,541 | 0.00% |
Per day, the shape is a volume story — cache read *per turn* is flat, and only the turn count moves:
| day | turns | cache read | cache read / turn |
|---|---:|---:|---:|
| 2026-08-27 | 4,393 | 799,300,233 | 181,949 |
| 2026-08-28 | 7,916 | 1,314,079,230 | 166,003 |
| 2026-08-31 | 2,413 | 420,977,195 | 174,462 |
| 2026-09-01 | 5,383 | 905,548,565 | 168,224 |
| **2026-09-02** | **9,054** | **1,424,404,888** | **157,323** |
**Caveat, stated up front:** cache reads are normally billed at a fraction of base input, so *96% of
token volume* is **not** *96% of the plan allowance*. I cannot see how the meter weights these
buckets. The table is directional — the quantity that grew is re-read context.
### A natural control: same machine, same user, two projects
I previously worked mostly in a different repository, on the 5x tier, and rarely hit the weekly
limit. I measured both projects rather than assuming the new one was heavier:
| | current project | previous project |
|---|---:|---:|
| transcript files | 2,507 | 6 |
| turns | 48,203 | 193 |
| active days | 17 | 4 |
| **cache read per turn** | **166,589** | **343,044** |
| **turns per day** | **2,835** | **48** |
| cache read per day | 472,356,992 | 16,551,888 |
**The obvious explanation is wrong.** The current project drags **half** the context per turn. What
changed by **58.8x** is **turns per day**, and consumption followed at 28.5x.
*(The comparison project is a small sample — 6 files, 193 turns, 4 days. Directional, not
equal-weight evidence.)*
### The fan-out mechanism
One `Workflow` invocation launched **280 subagents** from a two-stage design its author reasoned to
about **70**. No loop, no crash, no retries — the arithmetic closed exactly:
stage 1 = 10 trackers
each returns candidates (design assumed ~2; actual mean 9, worst 15)
stage 2 = each candidate x 3 lenses
10 + (90 x 3) = 280
**The unbounded quantity was the stage-1 yield, which multiplies.** A declared *total* would not have
caught it — the author did reason about scale and arrived at ~70 in good faith. Nothing surfaced a
projection, and nothing required a cap on the multiplying term.
**The design error was mine.** I am not reporting it as a defect. I am reporting that at ~165k tokens
of context per turn, a fan-out that multiplies turns is the single most expensive thing a user can
do, and it is the one the product asks least about.
### On #91623 — I tested its hypothesis and could NOT reproduce it
[#91623](https://github.com/anthropics/claude-code/issues/91623) reports a Max 20x plan going
0% -> 88% weekly in ~22 hours on **2026-09-02**, the same date, attributing it to
`claude-fable-5-1` emitting **2.04x** the output tokens per turn of `claude-fable-5`, after an
automatic update to `2.1.257` migrated `fable`-aliased sessions without notice.
**On my machine the ratio is the other way:**
| model | turns | output / turn |
|---|---:|---:|
| `claude-fable-5` | 2,501 | **2,167** |
| `claude-fable-5-1` | 678 | **1,843** |
| `claude-opus-5` | 45,499 | 1,360 |
**Ratio here: 0.85x — 5.1 emitted *fewer* output tokens per turn, not more.** I am on `2.1.259`,
past the update it describes, and Fable here was **only ever invoked as a subagent, never as an
orchestrator**, and still consumed 50% of its bucket in the window.
I report this because it is contrary to my own interest: it is a negative result against a public
hypothesis, measured on real data, and it points the investigation somewhere else — at cache reads
rather than output tokens.
### On #78768 — same shape, and it is open with no response
[#78768](https://github.com/anthropics/claude-code/issues/78768) (`area:cost`, `duplicate`, open)
reports hitting the limit immediately on resuming a session:
*"Feels like context was reloaded to LLM and it was counted as usage (but it is not, only
continuation of old session with old context)."*
That is the same **class** as the measurement above — consumption dominated by context re-entering
the meter rather than by work performed. **I am not claiming the same cause**; I have not reproduced
it and I cannot see the meter. I raise it because it is labelled a duplicate, so there are others,
and it has no staff response.
### What would help
In rough order of how much I think each would have changed my outcome:
1. **Show projected fan-out before execution, and require an explicit ceiling when a stage maps over
a prior stage's results.** The word *unbounded* alone would have stopped the 280-agent run. The
number that needed to be visible was never the orchestrator's overhead — it was the count about
to be launched, at the moment of launching.
2. **A user-configurable, runtime-enforced cap on cumulative subagents per run and per session.** A
session-level guideline the model can reason around is not a control — mine reasoned around it in
writing before executing.
3. **A live agent counter during execution**, so a run passing 100 is visible while it still is one.
4. **Surface cache-read per turn per session.** Given the numbers above, this is the single most
useful figure a heavy user could see, and today it is discoverable only by parsing your own
transcripts.
5. **Treat each multiplying term as its own object.** A declared total is fully compatible with an
unbounded product.
### What Should Happen?
Before executing, a Workflow whose second stage maps over the first stage's
results should tell me how many subagents it is about to launch — and when that
count depends on a prior stage's yield and is therefore not knowable in advance,
it should say so and require an explicit ceiling on that term before running.
Instead it ran silently and launched 280 subagents from a design intended for
~70. The total was never wrong in the script; it was never computed anywhere the
user could see it. A declared total does not help, because the author does reason
about scale — the unbounded quantity is the middle term, and nothing asks about
it.
Secondarily: consumption attributable to re-read context should be visible per
session. It is 96% of my token volume and ~165,000 tokens on every turn, and
today the only way to discover that is to parse your own transcripts.
### Error Messages/Logs
```shell
None. There was no error, no crash, no retry and no warning — that is the
report. Exit status was success and the arithmetic was exact:
10 + (90 x 3) = 280.
Aggregate telemetry is in the body; raw transcripts are not attachable, as they
contain third-party personal data under Brazilian data-protection law. I can
supply any additional aggregate on request.
Steps to Reproduce
Reproducing the aggregation
Walk ~/.claude/projects/**/*.jsonl recursively; for each line with message.usage, key onmessage.id and keep the maximum of cache_read_input_tokens,cache_creation_input_tokens and output_tokens; group by message.model and by date.
Print the number of files scanned — a non-recursive glob silently excludes the subagent
transcripts, which is where the partials live.
### Claude Model
Not sure / Multiple models
### Is this a regression?
I don't know
### Last Working Version
_No response_
### Claude Code Version
2.1.259
### Platform
Anthropic API
### Operating System
Other Linux
### Terminal/Shell
VS Code integrated terminal
### Additional Information
_No response_