When you hit 429 Too Many Requests (rate limiting), wait and retry with exponential backoff instead of hammering the server.
When you hit 429 Too Many Requests (rate limiting), wait and retry with exponential backoff instead of hammering the server.
# curl's built-in retry honors Retry-After on 429/503:
curl --retry 5 --retry-delay 1 --retry-max-time 60 \
--retry-all-errors https://api.example.com/dataasync function withRetry(url, opts = {}, max = 5) {
for (let i = 0; i < max; i++) {
const res = await fetch(url, opts);
if (res.status !== 429) return res;
const ra = res.headers.get('Retry-After');
const waitMs = ra ? Number(ra) * 1000
: Math.min(2 ** i * 1000, 30000);
const jitter = Math.random() * 250;
await new Promise(r => setTimeout(r, waitMs + jitter));
}
throw new Error('rate limited: retries exhausted');
}import time, random, requests
def get_with_retry(url, tries=5):
for i in range(tries):
r = requests.get(url)
if r.status_code != 429:
return r
ra = r.headers.get('Retry-After')
wait = float(ra) if ra else min(2 ** i, 30)
time.sleep(wait + random.uniform(0, 0.25)) # jitter
raise RuntimeError('rate limited')Check the `Retry-After` header first. The server tells you, as a number of seconds or an HTTP-date, when it is okay to try again. When present, honoring it is the most accurate; when absent, compute your own backoff.
Grow the delay exponentially (1s, 2s, 4s, 8s…), but always add random jitter. Without jitter, every throttled client retries at the same instant and re-overwhelms the server — a thundering herd. Cap the maximum wait (e.g. 30s).
Apply the same strategy to 503 Service Unavailable, not just 429. Be careful retrying non-idempotent requests like POST — retrying blindly risks duplicate processing, so only do it when you have an `Idempotency-Key` or the operation is otherwise safe. Many APIs also expose `X-RateLimit-Remaining` and `X-RateLimit-Reset` so you can back off before hitting the limit.