CLAUDE LABJP
RELEASE — Claude Code v2.1.243 shipped on August 25 with broad improvements across usage reporting, model selection, sign-in, and reliabilityUSAGE — /usage now breaks results down per loop, showing run count, total tokens, tokens per run, and last run, which makes a chatty /loop task easy to spotSETTINGS — modelPicker lets you curate the /model list with your own order and labels, while promptCacheTtl and subagentPromptCacheTtl let the main conversation and subagents keep different cache lifetimesLOGIN — /login now offers keyless sign-in with an Anthropic Console account, so organizations that do not permit API keys can still get inPERFORMANCE — The native binary is now zstd-compressed, dropping from roughly 340MB to 75MB on Linux x64, and each session uses about 40 to 60MB less memoryFIX — v2.1.245 resolves a startup crash on distributions shipping glibc 2.44, including Arch Linux, CachyOS, and Fedora RawhideRELEASE — Claude Code v2.1.243 shipped on August 25 with broad improvements across usage reporting, model selection, sign-in, and reliabilityUSAGE — /usage now breaks results down per loop, showing run count, total tokens, tokens per run, and last run, which makes a chatty /loop task easy to spotSETTINGS — modelPicker lets you curate the /model list with your own order and labels, while promptCacheTtl and subagentPromptCacheTtl let the main conversation and subagents keep different cache lifetimesLOGIN — /login now offers keyless sign-in with an Anthropic Console account, so organizations that do not permit API keys can still get inPERFORMANCE — The native binary is now zstd-compressed, dropping from roughly 340MB to 75MB on Linux x64, and each session uses about 40 to 60MB less memoryFIX — v2.1.245 resolves a startup crash on distributions shipping glibc 2.44, including Arch Linux, CachyOS, and Fedora Rawhide
Articles/API & SDK
API & SDK/2026-07-12Advanced

A Long Non-Streaming Response Was Billed Twice Past the 10-Minute Wall: Redesigning the SDK's Default Timeout and Retries

The Anthropic SDK's default 10-minute timeout and two automatic retries can silently re-run a long non-streaming response and bill you twice. Here is how the trap works, and how to close it with streaming, explicit timeout/max_retries, and a small local ledger — with measured before/after numbers.

Claude48API28SDK4timeout10cost-optimization29

Premium Article

One week, the cost of my nightly batch crept up for no reason I could see. The number of summaries generated was the same as the week before, the number of articles processed was the same, yet the api-sdk line on the bill kept climbing. It took me half a day to find the culprit, and it was hiding somewhere I never thought to look.

I had a summarization task with max_tokens raised to 16,000, and I had written it the plain way: call client.messages.create(...), take the text back. During busy hours, though, that generation occasionally took nine to eleven minutes. And the Anthropic SDK's default request timeout is exactly ten minutes.

Cross that line by a single second and the SDK's read timeout fires. The SDK treats it as a transient failure and, under its default retry policy (up to two attempts), sends the same request again. Here is the trap: the first request is still generating on the server, and if it finishes, you are billed for the output tokens it produced. Then the retry runs as a second, independent request and bills you again. I receive one response, but I pay for two. That was the quiet cost creep.

What follows is a breakdown of that mechanism down to the SDK's behavior, and the three design changes that stop the double charge at the root — with the code I actually put into my nightly batch. If you run unattended jobs across a few sites as an indie developer, this is exactly the kind of spend you can keep paying without ever noticing.

Misreading the defaults bites hardest when nobody is watching

Start with the two defaults the SDK carries silently. In the Anthropic Python SDK, both of these are in effect the moment you construct a client.

SettingDefaultWhat it means for unattended jobs
timeout10 minutes (600s)A long generation that exceeds 10 minutes triggers a read timeout
max_retries2On transient errors, including timeouts, the same request is resent up to twice

Automatic retries are a good feature in general. For errors like 429 (rate limit), 5xx, or a dropped connection — the "just send it again and it will go through" kind — exponential backoff with jitter works well. The problem is that a read timeout is not that kind of error.

A timeout is only a signal that the client gave up waiting. The server has no idea about your side and keeps generating. Messages API billing is charged against the output tokens that get produced. So the first request, even if you never receive it, is billed once it completes. Layer a retry on top and you pay twice for the same generation.

The SDK is aware of this danger. For a non-streaming request with a large max_tokens, it emits a warning that the request may exceed ten minutes and recommends streaming instead. I am a little embarrassed to admit I had been scrolling past that warning in my logs for a long time. The warning was right.

Why timeout retries specifically are the dangerous ones

Separating the safe retries from the dangerous ones is where the design clicks into place.

Failure typeServer-side stateRetry safety
429 / 529 (overloaded)Request rejected, not processedSafe. A resend is billed once
Connection failureRequest never reached the serverSafe. Nothing was generated yet
Read timeoutRequest in flight, likely still generatingDangerous. Double-billed if it completes

The key fact is that a single Messages API request has no idempotency key — no Stripe-style mechanism that folds a re-sent request into one. Unless we track "this is a resend" ourselves, the two requests are entirely separate as far as the server is concerned. That is precisely why retries that involve a timeout must not be delegated to the SDK.

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
A breakdown of how the SDK's default 10-minute timeout plus two automatic retries quietly re-run a long non-streaming request and double the bill
Working code that stops the double charge with streaming, explicit timeout and max_retries, and an idempotent local ledger
The exact settings that took duplicate-billing from roughly 2% to zero in a nightly batch, plus how to verify it
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 $15 for lifetime access
View Membership →

Related Articles

API & SDK2026-07-24
When Memory Store Listings Returned Half the Rows: Migrating to agent-memory-2026-07-22
agent-memory-2026-07-22 changed memories.list: fixed ordering, stricter depth, segment-based path_prefix matching. How an audit quietly halved, an access layer that survives it, and measured depth=1 traversal cost.
API & SDK2026-07-14
A Two-Stage Pre-Publish Gate for User-Facing AI Text in Consumer Apps
Design a two-stage pre-publish gate for short AI-generated text you ship to end users: a deterministic rule layer plus a Claude classifier, with fail-closed handling, generation-time vetting, and a cost model. Full implementation code included.
API & SDK2026-06-22
Drop Your Static Claude API Keys: Moving CI and Production to Keyless Auth with Workload Identity Federation
Workload Identity Federation is now generally available on the Claude Platform. This guide walks through replacing long-lived sk-ant- keys with short-lived OIDC tokens, including keyless GitHub Actions auth, the migration steps, and token refresh design.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →