429 Too Many Requests — what to do
A 429 is not a failure, it is a request to wait. How to retry properly and why agent workloads hit it soonest.
2 min · · Updated · errors · limits · reliability
A 429 means too many requests in a given period. It is not a failure and not a key problem: the service is asking you to wait and try again.
How 429 differs from its neighbours
They are easy to confuse and are fixed differently.
429 — you hit a request-rate limit. Wait and retry.
402 — your balance is empty. Waiting will not help; top up.
503 — the service or the model provider is temporarily unavailable. Also retry, but with longer intervals.
The first thing to check on any error is the status code, not the message. Wording varies between providers; codes do not.
An important caveat about Zukko: the gateway has no request-rate limit of its own. A 429 from Zukko itself means the key hit its spending limit — code key_daily_limit_reached (daily limit, resets at 00:00 UTC) or key_monthly_limit_reached (monthly). Retries will not help here: raise the key's limit in the dashboard or wait for the reset. Every other 429 comes from the model provider — those are the ones a backoff retry fixes.
Retrying properly
An immediate retry almost always earns a second 429 and makes things worse: you add load exactly when there is already too much.
Exponential backoff with jitter works. Start at one second, double each time, and add a random offset so your own parallel workers do not all knock at once.
import random, time
for attempt in range(6):
response = call_api()
if response.status_code != 429:
break
retry_after = response.headers.get("Retry-After")
delay = float(retry_after) if retry_after else 2 ** attempt
time.sleep(delay + random.uniform(0, 0.5))If the server sends a Retry-After header, its value outranks your formula — it states how long to actually wait.
Cap the number of attempts. An unbounded retry loop turns a temporary annoyance into a hung process you discover an hour later.
Why agents hit 429 first
Agent workloads — Claude Code, autonomous pipelines, parallel file processing — issue requests in bursts and often in parallel. Ten concurrent branches produce ten times the rate while each individual branch looks modest.
What helps is capping concurrency explicitly rather than hoping. Five simultaneous requests instead of twenty usually does not slow the overall job, because the bottleneck is the model provider's limit, not your own speed.
When it is not your fault
If a 429 arrives on the very first request after a long idle period, read the code in the response body first. key_daily_limit_reached or key_monthly_limit_reached means the key's spending limit set in the dashboard was hit (the daily one resets at 00:00 UTC). Any other 429 is a limit upstream at the model provider, and someone else exhausted it. If retries do not help, ask support which limit was hit.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- OpenAI API Keys in the Open: Why You Should Not Use ThemWhere free keys on GitHub come from, why using them is dangerous for you and for the owner, and how to protect your own key from the same leak.
- GLM API Errors: Why the Request Fails and How to Fix ItA wrong model id, an overflowing 128K context, the key, the balance, limits: the typical causes of GLM API errors and a quick way to find yours.
- This organization has been disabled in the Claude API: What to DoAn Anthropic key suddenly answers "organization has been disabled". What the error is, what to check, and how to move the SDK and Claude Code to another provider.
- JetBrains AI Assistant not working: causes and workaroundsAI Assistant will not activate, stays silent or is off for some files. We go through the causes in the JetBrains docs and connect your own models via a gateway.