[Bug] Resume sessions write ephemeral_5m cache instead of ephemeral_1h, wasting 70-140k tokens per resume

Resolved 💬 1 comment Opened Apr 13, 2026 by Przemotar Closed May 25, 2026

Bug Description
TITLE: Resume sessions waste ~70-140k cache_creation tokens due to 5m → 1h TTL transition gap

SUMMARY:
After /resume on a long session, the first assistant response writes the cache as
ephemeral_5m_input_tokens instead of ephemeral_1h_input_tokens. The next user message (often
within 3-5 minutes) does NOT hit that 5m cache (cache_read=0) and writes a fresh 1h cache for nearly
identical prefix. This double-pays the cache write cost on every resume — ~70k cr (5m write) + ~140k
cr (1h write) = ~210k cr wasted for a 200k context session.

REPRO (real session, jarvis project, sessionId 4c6631e4-f283-4f19-85e5-b292760651c3):

Timeline 8h after closing the session, on /resume:
08:08:36 ASSIST cr=0 cw5m=209,013 cw1h=0 ← turn 1 writes 5m cache
08:10:51 USER "Chcę opcję full..."
08:12:19 ASSIST cr=0 cw5m=0 cw1h=211,487 ← turn 2 writes NEW 1h cache (5m never
hit!)
08:13:03 ASSIST cr=211,487 cw5m=0 cw1h=7,456 ← turn 3 hits 1h cache normally

Gap between turn 1 and turn 2 was 3m 42s — well within 5m TTL — yet cache_read=0 in turn 2.

PATTERN ACROSS SESSION:

  • 274 of 280 assistant messages used 1h cache (active session steady state)
  • 6 used 5m cache — and those 6 are concentrated around session resumes / first-message-after-pause
  • Only the FIRST message after /resume gets 5m TTL; second message onwards is 1h

WHY THIS IS A REAL COST:

  • Opus 4.x cache_write_1h ≈ 2× input rate (~$30/1M)
  • 200k token context resume = ~70k cr 5m write + ~140k cr 1h write
  • 5m cache is never read (turn 2 invalidates it by writing fresh 1h)
  • Across all Claude Max users, this aggregates significantly

LIKELY ROOT CAUSE (hypothesis — please verify against Claude Code source):
First request after /resume sends cache_control: {type: "ephemeral"} without explicit ttl: "1h",
defaulting to 5m. The 1h flag is set from the second sustained-activity request onwards. This may be
intentional ("don't pay 1h price if user just peeked and left") but in practice users /resume to
continue work, not to peek.

SUGGESTED FIX:
Either:
(a) Always set ttl="1h" for first /resume request when previous session activity duration > N minutes
(signal of sustained work)
(b) Detect resume context and set ttl="1h" if context > 50k tokens (cache write cost > 1h price
difference)
(c) Add config flag cacheResumeTtl: "1h" | "5m" | "auto" for users to opt in

WORKAROUND for users (current):
Send a short throwaway prompt right after /resume (e.g. "/status" or "hello"), wait a few seconds,
then send the real prompt. The first message gets the 5m write (which we have to pay anyway), the
second promotes to 1h, and the third is the real work — which now hits 1h cache properly. Saves ~140k
cr per resume on a 200k context session.

REPRO TOOL:
Wrote a Python analyzer that detects this pattern in any Claude Code session JSONL:

  • Detects cache_creation_5m vs 1h split per assistant message
  • Flags anomalies: cacheRatio < 15% AND total context > 5k
  • Classifies CACHE_INVALIDATION (gap < 1h) vs NATURAL_EXPIRY (gap >= 1h)
  • Outputs per-anomaly cost estimate using cc-inspector calibration (cache_write_1h ≈ 0.667× input)

Happy to share if useful.

Environment Info

  • Platform: win32
  • Terminal: windows-terminal
  • Version: 2.1.104
  • Feedback ID: 0f7ce993-842a-4d7d-9b3d-ecd67e82a51e

Errors

[]

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗