429 Too Many Requests: Rate Limits, Retry-After and False Alarms
A 429 Too Many Requests means you hit a rate limit: the server is healthy and is deliberately refusing extra requests from this client for a while. It is a throttle, not an outage, and the response usually tells you exactly how long to wait.
What a 429 means and what comes with it
429 is defined in RFC 6585 as the status for rate limiting: the client has sent too many requests in a given amount of time. The specification deliberately leaves two things open: how the server identifies the client, and how requests are counted. That is why rate limits differ so much between services.
In practice, servers count per IP address, per API key, per session, per account, or per combination of those, and they use fixed windows, sliding windows or token buckets. Two identical request rates can therefore be fine on one endpoint and blocked on another on the same site.
The response carries the signals you need:
Retry-Afteris the standard one. RFC 9110 allows either a number of seconds or an HTTP date, and a well-behaved client waits that long before retrying.- Rate limit headers such as
RateLimit-Limit,RateLimit-RemainingandRateLimit-Reset, or the olderX-RateLimit-variants, expose the budget and when it resets. These are conventions, not part of RFC 9110, so check the API documentation for the exact names. - The body should explain the limit in human-readable terms. Many APIs name which quota was exceeded, which saves a lot of guessing.
A 429 is not cacheable by default, so intermediaries should not keep serving it once the window resets.
Rate limit or real outage?
These get confused constantly, because both show up as failing requests. The distinguishing tests are quick:
- The code itself. A rate limit answers 429. An overloaded or maintenance-mode server answers 503. Both may carry
Retry-After, which is why people mix them up, but they mean different things: 429 says "you specifically are sending too much", 503 says "the service as a whole cannot take work right now". See the 503 guide for that side. - Response time. Rate limits reject fast, usually in milliseconds, because the decision is made before any real work happens. Overload responds slowly or times out.
- Who is affected. A rate limit hits one client identity. Test from a different IP address or with a different API key: if that succeeds while the throttled client still fails, it is a limit, not an outage.
- The pattern over time. Rate limiting is periodic and self-clearing. Failures cluster, then stop exactly when the window resets, then return. An outage does not politely resume on a schedule.
- Correlation with your own volume. If failures started when you raised a check frequency, added parallel workers or launched a batch job, the cause is on your side of the connection.
Why monitoring can trigger a 429 on itself
Monitoring is a repeating request from a small set of addresses to the same URL, which is close to the shape rate limiters are built to catch. A very short check interval makes that worse, because every-minute checks multiplied by many monitored URLs add up quickly against a per-IP budget. So does running a check from many locations at once: the origin sees a burst rather than a steady trickle, and burst limits fire first.
The choice of URL matters as well. Search pages, API endpoints and anything that writes are usually limited harder than a static homepage. And if monitoring and the application share one API key, the two compete for a single quota. The result is a monitor that reports the site as failing while the site is entirely healthy, and a rate limiter doing its job correctly.
How to fix a 429
- Read the response headers before changing anything:
curl -sS -o /dev/null -D - https://example.com/api/itemsRetry-Afterand any rate limit headers tell you the real budget, which beats guessing at intervals. - Respect
Retry-After. Retrying immediately extends the block on many implementations. Wait the stated time. - Back off exponentially with jitter in client code, so concurrent clients do not synchronize and retry in a thundering herd.
- Lower the request rate. For monitoring, move a checked endpoint to a longer interval, or stagger checks so that many locations do not fire in the same second.
- Monitor a cheap, representative URL. A lightweight health endpoint or the homepage tells you the site is up without spending the quota you need for real traffic.
- Exempt the monitoring client at the limiter. Allowlist the checkpoint addresses, or give monitoring its own API key with its own budget, so it never competes with production traffic.
- If you own the limiter, check the limit is right. Ask whether the budget matches real usage, whether it is per IP when it should be per account, and whether shared proxies or corporate NAT are putting many users behind one address.
Watching for 429s without causing them
Rate limits usually appear first for the busiest clients, which means paying customers and integrations hit them before anyone on your team does. A scheduled HTTP check that asserts the expected status code shows a 429 as a distinct, timestamped event rather than as scattered reports of "the API is flaky", and the timing tells you whether the limit is periodic or permanent. Set the interval deliberately: often enough to notice problems quickly, gentle enough that the check is never the thing tripping the limit. The wider family of refusals, including 401 and 403, is covered in the 4xx overview.