Debugging / Throttling
Rate Limit Issues
A 429 tells you to slow down, and the response headers tell you by how much. Read them instead of guessing at a retry delay.
Reference
Read the rate limit headers
A throttled response carries everything you need to schedule the next attempt. Read these instead of choosing an arbitrary delay.
HTTP 429 Retry-After: 2 # seconds to wait before trying again X-RateLimit-Limit: 100 # requests allowed in the window X-RateLimit-Remaining: 0 # requests left right now X-RateLimit-Reset: 1754053200 # when the window resets
- Retry-After
- The wait before your next attempt. Honour it, then add a little random jitter so your instances do not retry in lockstep.
- X-RateLimit-Remaining
- Also present on successful responses, so you can slow down before you are throttled.
- X-RateLimit-Reset
- When the current window resets, useful for scheduling deferred work.
- 429 is not an outage
- It means too many requests arrived too quickly. Reducing concurrency fixes it; retrying harder makes it worse.
Client fix
Back off correctly
if response.status_code == 429:
wait = float(response.headers.get("Retry-After", 1))
time.sleep(wait + random.uniform(0, 0.5)) # jitter avoids a retry storm
# and lower concurrency — the limit is per interval, not per attempt- Cap total attempts so a sustained limit cannot turn into an infinite loop.
- Move batch and backfill work off the interactive path so it cannot throttle user-facing calls.
- If you see 429 in normal operation rather than during bursts, your steady-state concurrency is too high.
Was this page helpful?