| invoice line | expected | actual |
|---|
| conversations over 20 turns | 11,240 | 12,980 |
| average billed input per 30-turn thread | 57k tokens | 883k tokens |
| prompt-cache hit rate | >70% | 6.4% |
| monthly input-token spend | ~$3.4k | ~$48k |
Monthly input_tokens climbed from 180M to 9.6B while p95 latency moved from 1.8s to 3.4s, a change small enough to miss the latency alert. The cost graph was the only real alarm: input_tokens in the OpenAI Usage dashboard had turned into a curve while user traffic stayed almost flat.
One exported trace made the shape obvious. Turn 1 sent the system prompt and the first user message. Turn 2 sent those again, plus the assistant reply and the next user message. By turn 30, the request contained the whole conversation twenty-nine times in aggregate across the thread’s lifetime. A single new 1,900-token exchange was not the unit of billing; the accumulating transcript was.
The cache miss was self-inflicted. The request began with diagnostic_time=2026-06-18T14:03:22Z, then the stable instructions, then the transcript. Because the volatile timestamp came first, the common prefix changed every turn, so cached prompt reads almost never applied. Moving diagnostics out of the prompt helped, but the main fix was to stop replaying everything: keep the recent turns verbatim, summarize older commitments into a bounded state object, and watch token slope per turn as a production metric.