Clément Farkas DauduFR

I measured my token spend, then got the conclusion wrong

TL;DR

Tokens, context and cache in two minutes

A turn is one round trip to the model, effectively one API call: the agent sends what the model needs to see, the model sends back a reply. Everything is counted in tokens, the chunks of text a model reads and writes, and priced per token.

What the agent sends each turn is the context: the fixed instructions it starts with (the preamble), plus everything the conversation has accumulated since, replies, files it read and tool results included. The whole context is sent again every turn, and paid for again, and it grows as the session goes on.

flowchart LR
  C["Context so far: preamble, messages, files, tool results"] -->|"sent again every turn"| M["Model"]
  M -->|"output tokens"| R["Reply"]
  R -->|"added to the context"| C

A session is one conversation with the agent. Starting a fresh session begins again from the preamble, with a smaller context that has to be written to the cache again.

Most of each turn's context is the same as last turn's, and the provider serves it from a cache. Input tokens come in three kinds:

The output is what the model writes back. Prices are multiples of the base input price. The ratios I use, plug in your own:

Token kind Price Compared with a cache read
Cache read 0.1× base input
Cache write 1.25× base input ~12.5×
Output 5× base input ~50×

So output is priced ~50× a cache read, which turns out to matter.

What 14 days of my transcripts showed

Billing basis, since it changes what "cost" means: I'm on a subscription, so none of this produces an invoice. Every cost figure here is modelled at API list price, which I'd argue is the right lens anyway, it's what the same work would cost on the API.

14-day window, my own local transcripts (the logs the agent keeps of each session), 682 sessions:

Measure Value
Input tokens that are cache reads 97.3%
Average context re-paid per turn 241,517 tokens
Sessions with peak context above 300k 33 sessions = 86.8% of cost
The two largest sessions (19,538 and 9,533 turns) 60% of the total
Output tokens, whole window 37.5M
Cache reads, whole window 13.1B

97.3% of input is not new content. It's the same context, re-sent, turn after turn. (Peak context is the largest context a session reached.)

The conclusion I drew: end sessions sooner

Output is 0.29% of all tokens. Cache reads are 97.3%. So the bill is context re-payment, a handful of sessions dominate it, and the lever is obvious: end sessions sooner, don't let context accumulate, and any tool promising to compress output is chasing a rounding error. The fix, I concluded, was session hygiene: end the session when the topic changes.

Clean story. Mostly wrong.

The measurement is still worth publishing. So is the mistake, because it's the kind that survives peer review by sounding obviously right.

The division that breaks it

Then someone did a division I hadn't done, and the conclusion fell over.

The two big sessions hold half the turns

Total turns implied by my own figures: 13.1B cache reads ÷ 241,517 average context = ~54,240 turns.

The two marathon sessions are 19,538 + 9,533 = 29,071 turns. That's 53.6% of every turn in the window.

Two marathon sessions Everything else
Turns 29,071 25,169
Cache reads 7.86B 5.24B
Implied average context per turn 7.86B ÷ 29,071 = ~270k 5.24B ÷ 25,169 = ~208k

They account for 60% of cost while containing 54% of the work. Which means they are barely more expensive per turn than everything else.

What ending a session actually changes

So the honest version:

20-25% is still real, and I'd still take it. But it's an ordinary optimisation, not the dramatic finding I thought I had. The 86.8% figure describes where spend is concentrated, and I read it as how much is recoverable. Those are not the same quantity and nothing in the data connected them.

Peak context is not average context

I also wrote that those sessions were "pinned near the 1M ceiling", the most context a session can hold. A ~270k implied average says otherwise. Peak context and average context are different numbers and I conflated them.

The fix isn't free either

Starting a fresh session re-writes the preamble and re-establishes context at the cache write tier, ~12.5× the price of a cache read.

That other 2.7% of input tokens I waved away as noise is cache writes plus fresh input. On 13.46B input tokens, 2.7% is ~363M tokens at 12.5× the read rate, which lands somewhere around a quarter to a third of the cache-read cost. Not noise.

So "end the session" has a break-even: below some accumulated context, splitting costs more in re-established cache than it saves in re-read context. I haven't computed mine. It's computable from data already on my disk, and I should have done it before recommending the behaviour to anyone.

Concentration is not waste

The bigger hole, and the one I'd want someone to point at in my own review.

86.8% of spend sitting in 4.8% of sessions is only a problem if those sessions weren't producing 86.8% of the value. They contained 54% of all turns. That's where over half the work happened.

I never separated "concentrated" from "wasteful". The entire prescription assumes they're the same thing. They might be. Long sessions do drift, carry irrelevant context, and re-read files nobody needs. But that's an argument I'd have to make with evidence about what those sessions produced, and I made it with evidence about what they cost.

Three levers, sized

Lever The numbers Verdict
Ending sessions sooner per-turn context ~270k -> ~208k roughly 20-25% less context per turn, minus new cache writes; break-even not computed
Compressing output 0.3% of tokens, ~12% of cost aimed at ~10-12% of the bill, not a rounding error
Trimming the static preamble 12,953 -> 10,075 tokens, against a 241k average context noise

Output compression is aimed at ~10-12% of the bill, not a rounding error. I said both "output is a rounding error" and "output compression targets ~10% of the bill" eight lines apart, which reads as a contradiction. Both are true in different units: output is 0.3% of tokens and ~12% of cost, because it's priced ~50× a cache read. Mark the unit or you'll confuse yourself, as I did.

The intuitive levers really are small. I trimmed my static preamble from 12,953 to 10,075 tokens. Against a 241k average context that's noise. I kept the change because shorter instructions are better instructions, not for the money.

Measure it yourself

Measure before you install anything. That advice generalises even though my conclusion didn't. What doesn't generalise is my distribution: 682 sessions in 14 days with two containing half the turns is one person's working style, and a fairly extreme one. Someone running many short scripted invocations in CI has the inverse shape, low per-turn context and high session count, and for them output compression matters considerably more.

The provider-reported usage is already on your disk. Claude Code writes it to ~/.claude/projects/**/*.jsonl.

Things I got wrong the first time, so you don't

The steps

  1. Glob the files.
  2. Filter out sidechain entries.
  3. Sum the four fields per assistant message.
  4. Multiply by your price table.
  5. Group by sessionId.
  6. Sort.

Twenty lines of Python.

Three questions for the result

Two questions to answer, and one to answer after them:

  1. Are cache reads dominating your input? If yes, your bill is context re-payment.
  2. Do a handful of sessions dominate those reads? If yes, look closer.
  3. Do those sessions also contain a proportional share of your turns? If yes, you've found where the work is, not where the waste is. That's the question I skipped.

Before you install a "token saver" tool

Same rules as any dependency, they just get skipped more often because the pitch is about saving you money.

I previously cited a "60.8% saved" figure from a CLI proxy I run. That's the tool grading its own homework, and my own notes record that the same proxy mangles certain command flags and reports false results. Citing it approvingly in an article about verifying claims was exactly the inconsistency a hostile reader should catch.

If you want to make a specific criticism of a specific tool, name it and link the lines that support the claim. Describing an identifiable project without naming it is the worst of both worlds: obvious to anyone who cares, unfalsifiable for everyone else, and the maintainer can't answer.

What I learned

Update, November 2026

Two measurements that change this piece. I had the first before publishing and left it out.

Bigger contexts are also slower. In August I measured latency on a different window, about 20k assistant turns bucketed by context size. Median wait per turn rises with context:

Context size Median wait per turn
0-100k tokens 4.9 s
100-200k 14.0 s
300-400k 19.8 s
800-900k 30.1 s

Re-reading a cached context is cheap, not instant. "The fix isn't free either" priced the split in cache tiers only and never counted the wall-clock that goes with a larger context. What the move from ~270k to ~208k is worth, I can't say: both sit in the 200-300k bucket, which that measurement doesn't report. That window's median context was 380k, so none of these medians plug into the cost figures above.

The model is a lever I left out. I wrote "The intuitive levers really are small", about trimming my preamble. That still holds. What I didn't consider is that the model tier is a lever of a different size. In September the same diff was reviewed in CI by Sonnet 4.6, then by Opus 5:

Reviewer model Cost Turns
Sonnet 4.6 $0.27 10
Opus 5 $1.31 24

That's 4.8×. On that repository a typical (median) Opus review cost about 2.2× a typical Sonnet 4.6 one; my notes don't record how many reviews that covers. That's per CI run, a different workload from the interactive sessions above, so I can't rank it against the 20-25%, which was a cut in per-turn context, not in the total bill.

The caveats are not small: