A 429 from an LLM API can mean a rate limit, an acceleration limit, or a spend cap. Only the first two are worth retrying. Read the error body and the retry-after header, wait as told, back off, and stop immediately on a spend cap error code.
Know the causes
The Claude documentation lists several reasons for a 429:
- You exceeded requests per minute, input tokens per minute, or output tokens per minute. The error says which one.
- An acceleration limit, which can trigger when your usage rises sharply. The docs advise ramping traffic gradually and keeping usage consistent.
- The monthly spend cap, with error code
enforced_spend_limit_reached.
The docs also note short bursts can exceed a limit even when your per minute average is under it, because a rate of 60 per minute may be enforced as one per second.
Use the header when present
When a 429 has a retry-after header, wait that many seconds. Earlier retries will fail. The docs say not every 429 carries it, and the spend cap one never does. If the header is missing on a rate limit error, use exponential backoff with jitter.
A decision table
- Error code is the spend cap code: do not retry. Alert a human, switch to degraded mode.
- Header present: wait the stated time, then retry once.
- Header absent, rate limit error: back off with jitter, cap the number of attempts.
- Acceleration limit suspected: slow the ramp, do not add concurrency.
Why retries cost money
Retry storms have a cost beyond errors. Every client that retries at once adds load, extends the throttling, and can duplicate work that eventually succeeds twice. If requests are not idempotent, you pay twice for the same output. Put a single retry budget per task and share it across layers, so a wrapper, an SDK, and a queue do not each retry three times.
Smooth the load
- Use a client side limiter that tracks tokens per minute, not only requests.
- Read the rate limit response headers, which report remaining and reset values for requests, input tokens, and output tokens.
- Move non urgent work to a batch API, which has its own limits.
- Use prompt caching. The docs say that for most models only uncached input counts toward the input token limit, so cache reads raise your effective throughput.
Queue instead of fail
For background work, put requests in a queue with a worker pool sized to your token rate, not your request rate. A queue turns a burst into a steady stream.
Quick check
Does max_tokens count toward the output token limit?
The docs say the max_tokens parameter does not factor into output token rate limit calculations, since only generated tokens count.
Should the SDK retry automatically?
For rate limits, yes with backoff. Make sure your own wrapper does not stack more retries on top, and that the spend cap error is not retried.
Sources
Last reviewed: 19 October 2026.