Trace API 429 Throttling Windows
Align 429 responses with rate-limit headers to reconstruct the client quota window and stop retries from extending the lockout.
Task
Correlate 429 responses with X-RateLimit headers to reconstruct the quota window and tune client pacing.
When to use this
A sync job receives 429 in bursts and then waits much longer than expected, because retries keep resetting its own budget.
Prerequisites
- Logs containing status codes and rate-limit headers
- A client job you can pace
- The provider rate-limit documentation
Steps
1. Extract quota headers alongside each 429.
grep -E 'HTTP/|x-ratelimit|retry-after' access.log | tail -20Expected output: You can align each 429 with remaining quota and reset timestamps.
2. Pace the client to stay under the limit and drop retries on 429.
if resp.status_code == 429:
wait = int(resp.headers.get('retry-after', '60'))
time.sleep(wait)
raise ClientThrottledException('pause sync')Expected output: The job pauses for the full window instead of retrying and extending the lockout.
Troubleshooting
Problem
410 after a long pause
Solution
Some providers count retries toward quota; confirm the reset header and avoid probing during the window.
Problem
Different limits per endpoint
Solution
Track quota per route, not globally, since limits often differ.
Limitations
- Requires providers to emit accurate rate-limit headers.
- Does not bypass limits; it only paces the client.
- Concurrency across multiple clients is hard to model without a coordinator.
What this recipe does
Correlate 429 responses with X-RateLimit headers to reconstruct the quota window and tune client pacing.
A sync job receives 429 in bursts and then waits much longer than expected, because retries keep resetting its own budget.
Prerequisites
- Logs containing status codes and rate-limit headers
- A client job you can pace
- The provider rate-limit documentation
Procedure
- Extract quota headers alongside each 429.
grep -E 'HTTP/|x-ratelimit|retry-after' access.log | tail -20
Expected result: You can align each 429 with remaining quota and reset timestamps.
- Pace the client to stay under the limit and drop retries on 429.
if resp.status_code == 429:
wait = int(resp.headers.get('retry-after', '60'))
time.sleep(wait)
raise ClientThrottledException('pause sync')
Expected result: The job pauses for the full window instead of retrying and extending the lockout.
How to confirm it worked
Run the commands above and confirm every expected result in order. If a step does not produce the stated output, use the troubleshooting notes before continuing. A passing run shows the job completes without 429 responses once paced to the reset window, and total wall time fits the quota math.
Troubleshooting
410 after a long pause — Some providers count retries toward quota; confirm the reset header and avoid probing during the window.
Different limits per endpoint — Track quota per route, not globally, since limits often differ.
Limitations
- Requires providers to emit accurate rate-limit headers.
- Does not bypass limits; it only paces the client.
- Concurrency across multiple clients is hard to model without a coordinator.