Advanced

When the server says slow down

I hammered an endpoint and it started failing. A 429 means too many requests, and the headers tell you how long to wait. Back off, do not blast.

What you will see

200

About 1 min of reading

Try It

Hit the rate limit and honor the wait instead of blasting.

1

Send too many requests. The server answers 429 with a Retry-After.

curl -si https://api.example/users | grep -E 'HTTP|Retry-After'

Before you run it, say out loud what it will print. Then open the answer.

What it prints
HTTP/1.1 429 Too Many Requests Retry-After: 30
2

Read the header and wait that long before the single retry.

sleep 30 && curl -s -o /dev/null -w "%{http_code}" https://api.example/users

Before you run it, say out loud what it will print. Then open the answer.

What it prints
200
Retrying immediately keeps you in the 429 zone. The Retry-After number is the server telling you the schedule. Sleep it, then retry once, not in a loop.

Data Flow

A 429 verdict carries a Retry-After hint; you sleep that long (or back off exponentially) and retry once, turning a flood into a gentle stream.
1 Server answers 429
↓
2 Retry-After gives a wait
↓
3 Sleep then retry once
↓
4 Back off doubles the wait
Why this works
Honor Retry-After

A 429 or 503 often carries Retry-After. Sleep exactly that long and retry once. Ignoring it and retrying immediately is what keeps you rate limited. The header is the server's gift, use it.

Back off exponentially

When the server gives no number, double your wait each failure (1, 2, 4, 8 seconds) and add a little randomness so parallel callers do not retry in lockstep. This converts a burst into a gentle stream.

Examples

The 429 verdict

429 Too Many Requests
Retry-After: 30

429 is a polite stop. Retry-After says wait 30 seconds. The server is telling you the schedule, not punishing you.

Wait then retry

if resp.status == 429:
    time.sleep(int(resp.headers['Retry-After']))
    retry()

Read the header, sleep that long, try once. Do not retry in a tight loop, that is what caused the 429.

Back off on your own

delay = 1
while True:
    r = call()
    if r.status != 429: break
    time.sleep(delay)
    delay *= 2

When no header is given, double the wait each try. Exponential backoff turns a flood into a trickle.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Pages, not the whole list
Previous Lesson
Pages, not the whole list
Next Lesson
Safe to retry
Safe to retry →