Skip to content
Agent Month

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

The fix

  1. 1Read the response: a 429 includes a 'retry-after' header telling you how many seconds to wait.
  2. 2Implement exponential backoff with jitter — most official SDKs retry 429s automatically (default ~2 retries); raise the limit if needed.
  3. 3Reduce token pressure: trim prompts, cache stable prefixes, and route low-stakes calls to a cheaper/separate model with its own quota.
  4. 4Batch non-urgent work through the provider’s batch API, which has separate, higher limits.
  5. 5If you’re consistently capped, request a tier/quota increase from the provider.

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.