[BUG] Parallel API during user turn cause significant prompt cache write penalty on Bedrock

Resolved 💬 4 comments Opened Mar 24, 2026 by lineardevon Closed Apr 22, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong

Claude Code fires 2–7 parallel API calls per user turn — not just at session startup. All calls receive identical inputs and independently write the prompt cache. This means every cache miss (TTL expiry, session start) incurs N× the necessary write cost instead of 1×.

Discovered by analyzing session JSONL transcripts at millisecond resolution. The signature is groups of JSONL entries with identical cache_creation_input_tokens and cache_read_input_tokens values, but timestamps 750ms–4s apart, each returning a different content block type (text, thinking, tool_use).

Evidence

Turn 1 of a session (v2.1.81, Bedrock Sonnet 4.6):

20:01:05.953Z  write=10,553  read=0  output=10   ['text']
20:01:06.715Z  write=10,553  read=0  output=10   ['thinking']
20:01:07.515Z  write=10,553  read=0  output=117  ['tool_use']

Three separate API calls, 750ms apart, identical inputs, each independently writing 10,553 tokens.

If these were sequential (each processing the previous call's output), the second and third calls would have larger inputs — they don't. If they were streaming events from one call, they'd be milliseconds apart — they aren't.

Turn 2 of the same session (warm-cache GOOD turn):

20:01:31.878Z  write=8,905  read=16,989  output=1    ['text']
20:01:35.486Z  write=8,905  read=16,989  output=408  ['tool_use']

Both calls independently write 8,905 delta tokens. One should write; the other should read.

TTL recovery event (one of 5 in the session):

14:37:40.xxx Z  write=124,192  read=0  output=0    ['thinking']
14:37:40.xxx Z  write=124,192  read=0  output=0    ['text']
14:37:46.000Z  write=124,192  read=0  output=0    ['tool_use']
14:37:52.000Z  write=124,192  read=0  output=882  ['tool_use']

4 parallel calls × 124,192 tokens = ~$3.10 in cache writes for what should cost ~$0.78 (1 write + 3 reads).

Distribution in one 304-entry session

Turns with 1 API call:  84
Turns with 2 API calls: 55
Turns with 3 API calls: 26
Turns with 4 API calls:  5
Turns with 5 API calls:  1
Turns with 7 API calls:  1

Every multi-call group has identical cache_creation_input_tokens and cache_read_input_tokens across all calls — confirming they share the same input state.

Cost Impact

For this session (304 JSONL entries, ~170 actual turns):

  • Measured input cost: $18.45
  • Estimated ideal (1 call/turn): ~$9

The multiplier is worst during TTL recovery: each expiry at large context size triggers N simultaneous full-context writes instead of 1.

Why This Differs from the Known Parallel Startup Writes

The 3–4 parallel startup write behavior is documented and accepted. What's described here is that the same pattern repeats at every turn — not only at session init. Mid-session turns with warm cache also fire 2–3 parallel calls, each independently writing delta tokens. The cost impact is smaller per-turn for warm turns but accumulates significantly over a long session, and is catastrophic on TTL recovery events.

Claude Code Version

2.1.81

Is this a regression?

Unknown — this may be intentional (speculative execution for latency), but it has significant cost consequences on Bedrock that weren't present or noticeable before longer/heavier sessions became common.

Platform

AWS Bedrock

Operating System

macOS Darwin 25.3.0

Terminal/Shell

zsh

Related Issues

  • #34629 — prompt cache regression in --print --resume
  • #37188 — cache_control TTL ordering with concurrent agents (Bedrock)
  • #36243 — 1h TTL not propagated to subagent requests on Bedrock

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗