HTTP 429 means “slow down, friend.” Your app is sending too many requests, too fast, and the server is waving a tiny digital stop sign.
TLDR: A 429 Too Many Requests error is not a server crash. It is a speed limit. If your app sends 1,000 API calls in one minute but the limit is 600, expect 400 angry rejections. The best fix is usually retry with backoff, plus smarter request design, such as caching, batching, or queues.
What does HTTP 429 mean?
A 429 status code means the API is saying, “Nope. Too many.”
It is like trying to enter a tiny coffee shop with 200 people at once. The coffee shop is open. The barista is alive. The espresso machine is fine. But the room is full, and someone needs to wait outside.
APIs use 429 responses to protect themselves. They also protect other users. Without limits, one noisy app could eat all the pizza. Nobody wants that.
A 429 response may include a helpful header:
- Retry-After: tells you how long to wait.
- X-RateLimit-Limit: tells you the max allowed requests.
- X-RateLimit-Remaining: tells you how many are left.
- X-RateLimit-Reset: tells you when the counter resets.
If the API gives you Retry-After: 10, do not retry after one second. That is rude. Also, it often fails again. Then your logs look like a raccoon got loose in them.
Rate limiting vs retry vs throttling
These terms get mixed up a lot. Honestly, it feels like every API doc uses them slightly differently. Still, the ideas are simple.
Rate limiting
Rate limiting is the rule set by the server.
Example:
- 100 requests per minute
- 5,000 requests per day
- 10 requests per second per user
- 3 login attempts per minute
The server tracks your requests. If you go over the line, you get a 429. Simple. Brutal. Fair.
Retry
Retry is what your app does after failure.
A good retry waits. A bad retry hammers the API like a toddler pressing an elevator button.
Good retry logic uses:
- Exponential backoff: wait 1 second, then 2, then 4, then 8.
- Jitter: add a random delay, so every client does not retry at once.
- Retry limits: stop after a few tries.
- Retry-After: follow the server’s timing when present.
Bad retry logic does this:
- Failure.
- Retry instantly.
- Failure again.
- Retry harder.
- Set production on fire.
Throttling
Throttling means slowing requests on purpose.
It can happen on the server side. It can also happen inside your app. For example, your client may decide to send only 20 requests per second, even if 200 jobs are waiting.
That sounds annoying. It is also smart. It keeps your app steady. It keeps the API calm. It keeps your support team from aging five years by lunch.
The 429 flow in plain English
Here is the usual story:
- Your app sends requests.
- The API counts them.
- Your app crosses the limit.
- The API returns 429 Too Many Requests.
- Your app reads the response headers.
- Your app waits.
- Your app retries carefully.
That is the happy path.
The sad path is when your app ignores headers and retries 300 times in 10 seconds. Expect to waste time on weird bugs when that happens. A page load that used to take 900 ms now takes 8 seconds. Your dashboard gets sad. Users click refresh. Now the problem is worse.
Common rate limiting methods
APIs use several methods to control traffic. You do not need a PhD to understand them.
Fixed window
You get a limit for a fixed time box.
Example: 1,000 requests per hour.
At the start of the next hour, the counter resets. This is easy to understand. It can be bursty near the edge of the hour.
Sliding window
This checks your usage over the last rolling time period.
Example: 1,000 requests in any 60 minute span.
It is smoother. It is also more work for the server.
Token bucket
Imagine a bucket that fills with tokens. Each request spends one token. If the bucket is empty, you wait.
This allows short bursts. Then it slows you down. Nice and polite.
Leaky bucket
Requests drip out at a steady pace. Big spikes sit in a queue. If the queue fills, requests get rejected.
This is great for smoothing traffic. It is less great if users expect instant action every time.
Smart retry rules that save your API
Use these rules as your anti-chaos kit:
- Respect Retry-After. If the server says wait 30 seconds, wait 30 seconds.
- Use exponential backoff. Start small. Grow the delay.
- Add jitter. Randomness prevents request stampedes.
- Set a max retry count. Three to five tries is often enough.
- Do not retry every error. A 400 bad request will not heal itself.
- Log rate limit events. You need numbers, not vibes.
A simple retry pattern may look like this:
- Try request.
- If 429, check Retry-After.
- If present, wait that long.
- If missing, wait 1 second, then 2, then 4.
- Add 100 to 500 ms of random jitter.
- Stop after 4 tries.
This avoids panic clicking at machine speed.
API throttling alternatives
Retries help after the problem happens. Better design can prevent the problem.
1. Cache repeat data
If the data does not change often, do not fetch it every time.
For example, product categories may change once a day. Cache them for 10 minutes or one hour. Your API calls may drop by 40% or more. Your users will not care. Your servers will.
2. Batch requests
Do not ask for one item 100 times. Ask for 100 items once.
This is like bringing one shopping list to the store. Not 100 tiny lists stuffed into your socks.
3. Use webhooks
Polling asks, “Anything new?” over and over.
Webhooks say, “Tell me when something happens.”
If you poll every 10 seconds, that is 360 requests per hour per customer. For 1,000 customers, that is 360,000 requests per hour. Ouch. A webhook may cut most of that.
4. Add a queue
A queue lets your app accept work now and process it at a safe pace.
This is perfect for email sending, file imports, report building, and sync jobs. Users get a “processing” message. Your workers handle the load without stampeding the API.
5. Limit concurrency
Too many requests at the same time can hurt, even if your per-minute count looks fine.
Set a cap. Maybe only 5 active requests per user. Maybe 20 per service. Tune it with real data.
6. Prefer incremental sync
Do not sync the whole universe every time.
Ask for records changed since the last sync. This can turn 50,000 records into 120 records. That is a very good day.
How to choose the right fix
Pick the fix based on the cause.
- Short traffic spikes? Use token bucket throttling and jitter.
- Repeated reads? Add caching.
- Large sync jobs? Use batching and incremental sync.
- Frequent polling? Switch to webhooks.
- Background tasks? Add a queue.
- Buggy loops? Add guards, logs, and alerts.
Also, talk to your API provider if your use is valid but blocked. Many providers offer higher plans or custom quotas. Bring numbers. “We need 2,000 requests per minute for nightly sync between 01:00 and 02:00 UTC” is better than “the API is being mean.”
What to monitor
You need visibility. Otherwise, 429 errors hide until users complain.
Track these metrics:
- 429 count per minute
- Retry success rate
- Average wait time after 429
- Requests per user or account
- Queue length
- API latency
If 429 errors rise from 1% to 12% after a release, roll back or slow down the new job. Do not stare at the graph and hope it becomes nicer. Graphs are not houseplants.
The simple rule
Rate limiting is the server’s boundary. Retry is your app’s reaction. Throttling is planned patience.
Use all three with care. Then add caching, batching, queues, webhooks, and better sync design. Your app will be calmer. Your API provider will be happier. Your users will just think everything works, which is the whole point.