How to fix: 429 rate limit error
Last verified: June 2026· OpenAI, Anthropic, and most LLM APIs
Where this shows up
OpenAI, Anthropic, and most LLM APIs
How it shows up
The same root cause surfaces in a few different ways. If any of these match, you're in the right place.
- HTTP 429 responses arriving in bursts rather than steadily, often right after a deploy or a batch job starts.
- A
retry-afterheader on the response that client code is ignoring in favour of its own backoff schedule. - Throughput that plateaus well below the documented limit because retries are consuming the same quota as first attempts.
- One noisy internal job starving a user-facing route, because both share a single API key and therefore a single bucket.
Diagnose it first
Confirm which cause you actually have before changing anything — most wasted time here comes from fixing the wrong one.
| Check | What the result tells you |
|---|---|
| Read the response headers, not just the status code. | Providers report which limit was hit — requests per minute, input tokens per minute, or output tokens per minute — and the remaining quota. Backing off for the wrong limit wastes the wait. |
| Plot 429s against your own request rate over a minute-level window. | If they cluster at the start of each minute you are bursting into a windowed limit; if they are spread evenly you are genuinely over capacity and need either higher limits or less traffic. |
| Check whether retries are counted in your own rate accounting. | A naive retry loop multiplies the traffic that caused the limit. If your client-side rate limiter counts only first attempts, it is under-counting badly during exactly the period it matters. |
| Identify which workloads share an API key. | Limits are usually per key or per organisation. A batch job and an interactive endpoint on the same key means the batch job can and will take down the endpoint. |
The fix
- 1Read the response: a
429includes a 'retry-after' header telling you how many seconds to wait. - 2Implement exponential backoff with jitter — most official SDKs retry 429s automatically (default ~2 retries); raise the limit if needed.
- 3Reduce token pressure: trim prompts, cache stable prefixes, and route low-stakes calls to a cheaper/separate model with its own quota.
- 4Batch non-urgent work through the provider’s batch API, which has separate, higher limits.
- 5If you’re consistently capped, request a tier/quota increase from the provider.
Provider-specific behaviour
The error means roughly the same thing everywhere, but each provider signals it differently.
- Token limits versus request limits
- Most providers enforce both, and long prompts hit the token limit long before the request limit. A workload that sends few but very large requests will be rate-limited while the request-per-minute counter looks comfortable.
- Windowing behaviour
- Limits are often enforced over a short rolling window rather than a clean calendar minute, so a client that fires its whole allowance at second zero will be throttled for the remainder even though the average is fine. Spreading requests evenly is usually worth more than raising the limit.
What doesn't work
Common fixes for this error that look right and aren't.
Retrying immediately in a tight loop.
This adds load exactly when the service is shedding it, extends the throttled window, and on some plans counts against the same quota you are waiting on.
Using a fixed sleep between retries.
Every client that hit the limit at the same moment wakes at the same moment, producing a synchronised second wave. Exponential backoff with jitter exists specifically to break that lockstep.
Asking for a limit increase as the first move.
It is often the right eventual answer, but a workload that bursts or retries badly will exhaust a higher limit too. Fix the shape of the traffic first, then raise the ceiling against a known profile.
Prevent it
Add a gateway that meters and queues requests, with backoff and per-route rate budgets, so spikes degrade gracefully instead of failing.
Common variations and related errors
You'll usually hit this same root cause under a few different names. Same fix.
- 429 Too Many Requests
- 429 rate limit exceeded
- "Rate limit reached"
- "You exceeded your current quota"
- "Requests per minute exceeded"
- "Tokens per minute exceeded" (TPM)
- openai.error.RateLimitError
- anthropic.RateLimitError
Code: drop-in retry helper
A minimal typescript helper that handles the most common version of this error. Copy, paste, adjust the policy to your traffic.
// Drop-in retry helper for 429s with exponential backoff + jitter.
// Use the response's 'retry-after' header when present, fall back to exponential.
export async function callWithRetry<T>(
fn: () => Promise<Response>,
parse: (r: Response) => Promise<T>,
opts: { maxRetries?: number; baseMs?: number; capMs?: number } = {},
): Promise<T> {
const { maxRetries = 5, baseMs = 500, capMs = 30_000 } = opts;
let attempt = 0;
while (true) {
const res = await fn();
if (res.status !== 429 && res.status < 500) return parse(res);
if (attempt >= maxRetries) return parse(res);
const retryAfter = Number(res.headers.get('retry-after'));
const backoff = retryAfter > 0
? retryAfter * 1000
: Math.min(capMs, baseMs * 2 ** attempt) * (0.5 + Math.random() * 0.5);
await new Promise((r) => setTimeout(r, backoff));
attempt += 1;
}
}Frequently asked questions
What causes “429 rate limit error”?
You exceeded the requests-per-minute (RPM) or tokens-per-minute (TPM) quota for your account tier.
How do I prevent “429 rate limit error” from recurring?
Add a gateway that meters and queues requests, with backoff and per-route rate budgets, so spikes degrade gracefully instead of failing.
Should I retry a 429 at all?
Yes, but only with exponential backoff and jitter, and only after honouring any `retry-after` header the provider sent — that value is authoritative and beats your own schedule. Cap the total number of attempts and fail the request cleanly rather than retrying indefinitely; an unbounded retry loop turns a brief throttle into a sustained outage and can cost more in tokens than the work was worth.
How do I stop a batch job taking down my user-facing feature?
Separate them at the key or project level so they draw on different quotas, and if that is not possible, put the batch work behind a client-side limiter configured well below your actual ceiling. Better still, move anything not user-facing onto a batch API where one exists, since those run against separate capacity at a lower price.
Does a rate limit mean I need higher limits?
Not usually, at least not first. The common causes are bursting into a short rolling window, retries that are not counted in your own rate accounting, and unrelated workloads sharing a key. Smooth the traffic, count retries, and split the keys — then ask for an increase with a traffic profile you can describe, which is also what makes the request easy to approve.