◉CLAUDE LABJP
●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…
Articles/API & SDK
⬡ API & SDK/2026-05-27Advanced

Tail Latency in Scheduled Claude API Workloads: A Three-Layer Guardrail Against Retry Storms

After running six sites in parallel through scheduled Claude API tasks for several months, 14 days of logs revealed three distinct p95/p99 patterns and a retry storm I had been creating from my own client. This is the guardrail design I landed on — jitter, budget, circuit breaker — with the before/after numbers.

Claude API128tail latencyretry stormproduction111scheduled workloadindie developer21

✦ Premium Article

I have been publishing apps as an indie developer since 2014. By the time the cumulative download count crossed 50 million, my workflow had drifted in the opposite direction of "ship more, automate more." I was spending more time watching what I had already built than building anything new. The last five months have been about running six sites in parallel — four Dolice Labs technology blogs plus two writing blogs in a separate folder — entirely through Cowork scheduled tasks. Claude API is the engine; GitHub and Cloudflare Workers are the rails.

A few weeks into that setup, one symptom kept catching my eye. A task scheduled to run at 02:00 JST was sometimes still running at 02:38. The API was responding. The retries were not. That gap — between "the model returned" and "the client gave up retrying" — is what this article is about.

The signal I missed when I only looked at p50

For the first few weeks I checked the average completion time and called it good. The median sat in a tight band, and the chart looked fine. The habit I inherited from my grandfather, who was a temple carpenter, is to keep touching the work until it tells you something. I started touching p95, p99, and the individual samples above 60 seconds, and the picture changed.

Latency itself was not the problem. The retry layer was misreading "slow but eventually fine" responses as failures, and was generating extra load from my own client. The same pattern I had hit before on the AdMob revenue side of indie apps: my retry policy was the dominant cause of the tail, not the upstream.

The shape of p95/p99 in 14 days of scheduled traffic

Here is the raw frame of the observation. Six sites, 14 days (2026-05-12 to 2026-05-25), 1,842 Claude API calls. Single requests, no streaming, a mix of claude-sonnet and claude-haiku.

MetricValue
Successful calls1,789 (97.1%)
Failed calls53 (2.9%)
p50 completion time7.4 s
p95 completion time19.8 s
p99 completion time41.2 s
Max187 s (outlier)
Avg retries on success0.18
Avg retries on failure4.6

A p99 of 41 seconds for an isolated call is acceptable on its own. The 4.6 average retries on failure is not. Every failure was triggering nearly five extra requests against the same endpoint. That is what I am calling a retry storm in this article.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦Three p95/p99 escalation patterns extracted from 14 days of scheduled Claude API traffic, with the observation queries that let me separate model jitter from self-inflicted retry storms
✦A working TypeScript implementation of a three-layer guardrail (jittered exponential backoff, per-minute budget, lightweight circuit breaker) sized for solo or small-team production use
✦Before/after numbers across p50, p95, p99, max latency, retry counts, and failure rate after rolling out the guardrails across 16 scheduled tasks per day
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

⬡ API & SDK2026-09-06
The translation read perfectly and still crashed at runtime
When you translate app strings with the Claude API, the meaning can be right while the format specifiers quietly break. Here is a severity-aware acceptance check and a repair loop that only re-translates the broken lines.
⬡ API & SDK2026-05-24
Archiving Claude API Responses to Cloudflare R2: An Implementation Memo for Audit, Replay, and Incident Analysis
An implementation memo on persisting Claude API requests and responses into Cloudflare R2 so you can audit, replay, and triage production incidents — covering Workers waitUntil patterns, PII masking, and a D1 metadata index for fast lookups.
⬡ API & SDK2026-10-16
Sending 40 Rows From Make to the Claude API Stops at Row 14 — Avoiding the 429 With One Subtraction
Why a no-code automation that sends spreadsheet rows to the Claude API one by one hits a 429 partway through, and how to fix it. Seven spacing strategies tested on a mock bucket, a formula for the Sleep delay, and settings that stop failed rows from vanishing.