reference
Living

Why your AI coding bill spikes

Your AI coding bill spikes when something breaks the model’s prompt cache — an idle gap past the cache’s lifetime, a model switch, an automation loop tuned to the wrong interval — and the next turn re-sends and re-processes the whole growing conversation as billed, uncached input instead of the usual fraction-of-a-cent cache read.

The number that changes isn’t how much work got done; it’s whether the turn hit the cache. Claude resends the entire session on every turn because the model remembers nothing between calls, and prompt caching is what keeps most of that resend nearly free. The spike happens when something knocks the next turn off the cached prefix — and the full history gets billed as fresh input instead. It isn’t waste in the way it feels; it is the visible edge of a caching boundary you didn’t know you’d crossed.

§01 · the symptom

The invoice doesn't match the work.

The bill lands and the first reaction usually isn’t “I did too much” — it’s “I did what I always do.” One developer, defending a $50,000 month of usage against accusations of gaming a $200 plan, put it as plainly as it gets: “I didn’t hack anything. I didn’t bypass limits. I simply used the service as it was offered.” That’s the shape of the complaint underneath most of these stories: nothing exotic happened, and the invoice still doesn’t look like the work.

Sometimes the spike isn’t even from heavy, deliberate use — it’s from routine automation left alone. One widely-read account, reported by MakeUseOf and sourced to a developer’s post in r/ClaudeAI, describes a loop set to check for updates every 30 minutes and left running overnight. By morning it had billed roughly $6,000. Not because the checks themselves were expensive — because every cycle rebuilt a roughly 800,000-tokenconversation history from scratch, dozens of times over the run, with nothing visible flagging the spend until the account’s usage limit tripped. (MakeUseOf, secondhand from Reddit)

§02 · why it happens

A cache boundary you can't see until you cross it.

Claude Code resends the whole session on every turn — the system prompt, tool definitions, project context, and the full prior conversation — because the model itself remembers nothing between calls. What keeps that resend cheap is prompt caching: the API matches the start of each request against what it already processed, and a hit is billed at a tenth of the fresh-input rate. A miss reprocesses everything from that point forward at full price, and writes a new cache entry at a premium — 1.25× the base input rate for a five-minute cache, 2× for a one-hour cache — before the next turn can benefit from it. (Claude Code docs)

The cache’s lifetime is the boundary that matters. The API supports two TTLs — five minutes or one hour — and Claude Code picks one automatically: on a Claude subscription it requests the one-hour TTL, so an ordinary break survives. But that TTL isn’t fixed for the whole session. Once an account has gone over its plan’s usage limit and Claude Code is drawing on paid usage credits, it automatically drops to the five-minute TTL, because writes to the one-hour cache cost more and the shorter TTL is cheaper to maintain under metered billing. (same docs, “Cache lifetime”)

That’s the mechanism inside the overnight story above. A 30-minute gap between automated checks comfortably survives a one-hour cache, but reliably outlives a five- minute one. Once the shorter TTL was in effect — whether from crossing a usage limit or any other cause — every cycle found a cold cache, paid full price to reprocess roughly 800,000 tokens of accumulated history, and wrote a fresh, more expensive cache entry that then expired before the next cycle could use it. Dozens of cycles a day, each one paying the write premium with none of the read discount.

§03 · what doesn't work

The obvious fixes, and where each one stops.

Set a spend cap and move on.A cap limits the damage once it fires, but by the overnight-loop math above the meter can run for hours before any limit trips, and a cap doesn’t explain — or prevent — a single cycle from repeatedly rebuilding the same history. It’s a circuit breaker, not a fix.

Just run the loop less often.This is the fix the MakeUseOf write-up itself recommends — keep automation intervals tight so the cache never goes cold. It works, but only for as long as five minutes is the right number to tune against. The TTL isn’t a fixed constant: it depends on plan and usage state, and a schedule tuned to a one-hour assumption breaks silently the moment an account drops to the five-minute one.

Switch to a cheaper model for background work.Sounds reasonable — off-hours checks don’t need the strongest model. But each model keeps its own cache, so switching is itself a cache-invalidating event: the very next turn on the new model pays full price for the whole history, once per switch. A loop that alternates models to save money can end up paying the miss penalty on a schedule instead of avoiding it.

Compact the conversation to shrink it.Compaction only changes what gets resent going forward — it replaces the message history with a summary, and producing that summary is itself a request that has to read the pre-compaction history first. If that read is warm it’s cheap; if the session has been idle past the TTL, the summarization call reprocesses the entire history as uncached input before it can produce a shorter one. It’s a rescue for a conversation that’s already grown large, not a way to avoid paying for the growth.

§04 · what actually helps

Know the boundary, and stop polling a growing conversation.

Two things generalize past the overnight-loop story specifically. First: know which TTL a session is actually on, not which one you assumed. Automation that polls on a fixed interval should be tuned to the shorter, five-minute boundary unless the session is confirmed to be holding the one-hour one — and that assumption is worth re-checking if the account has ever crossed a usage limit, since that’s a documented trigger for the drop. Second: watch the ratio, not the invoice. Claude Code reports cache-read and cache-creation token counts on every turn, visible live through a statusline script or aggregated per session through the OpenTelemetry exporter — a creation count that stays high turn after turn is the leading indicator, hours before the bill confirms it.

The non-product fix is the oldest one in the automation playbook: don’t run a fixed-interval polling loop against a growing conversation at all. An update check, a PR-status poll, or any routine background task is usually better served by a short, stateless call or an event-driven trigger than by resuming one long-lived session every thirty minutes indefinitely. The $6,000 didn’t come from the checking; it came from the checking being bolted onto a conversation that kept growing and kept going cold.

And treat model and effort switches as deliberate choices inside a long session, not casual ones — each one pays the full re-read once. Picking a model and effort level at the start of a session, and saving compaction for natural breaks rather than mid-task changes, keeps the cache doing its job instead of resetting it.

§05 · the receipt

What disciplined cost actually looks like.

Set against the horror stories, here’s one measured session from our own production telemetry — not a benchmark, a live workload, with no update-loop and no idle overnight gaps. Across 11,232 turns, 99.974% of what the model reasoned against on each turn was served from cache, at an average of $0.181 per turn.

What was measuredThe number
turns in one session11,232
cache hit rate99.974%
average cost per turn$0.181
fresh input tokens per turn≈ 116
where it's fromVinculum production telemetry, 2026-06-09 — one live session, measured, not a benchmark
§06 · where a substrate fits

It doesn't touch the cache. It changes what a cold one costs.

A substrate doesn’t intercept API calls, run a second cache, or change the per-token price — none of the mechanism above is something a memory layer can override. The cache and a substrate solve different parts of the same problem: the cache discounts repeats within a session; a substrate is aimed at what a session starts with.

What changes is the cost of going cold. If the standing record of a project lives outside the conversation, a session that crosses a TTL boundary — idle overnight, a forced restart, a fresh start the next day — doesn’t need an 800,000-token history kept warm to stay useful. Re-orienting is a handful of targeted reads instead of one enormous transcript that either survives the cache or gets rebuilt at full price. The cache still expires. It just stops being the thing a whole conversation’s cost depends on.

§07 · common questions

Common questions.

Does prompt caching itself cost money?

Writing to the cache costs more than a plain input read — 1.25× the base rate for a five-minute cache, 2× for a one-hour cache — and that premium is only recovered if a later turn actually hits the cache, billed at 0.1× the base rate. A session that keeps writing and rarely reading, the overnight-loop pattern below, pays the premium without the payoff.

Is the $6,000 overnight-loop story typical?

No, and it isn’t presented as typical here. It’s a secondhand account — reported by MakeUseOf, sourced from a developer’s post in r/ClaudeAI — of an edge case: unattended automation on a polling interval that outlived the cache it depended on. See the receipt below for what a disciplined, attended session actually costs.

Does a substrate change the cache's TTL or pricing?

No. A substrate doesn’t intercept API calls, run a second cache, or change the per-token price at the API layer. What it changes is described in where a substrate fits below.