429 Too Many Requests means the server is rate limiting you: you've sent more requests in a given window than it allows, so it refused this one without processing it. It isn't a failure of the server. It's a request to slow down, and the response often says exactly how long to wait in a Retry-After header.
HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json
{"error": "rate_limited", "message": "Too many requests, retry in 30 seconds"}
Common causes
- An API's rate limit. GitHub, Stripe, OpenAI, Shopify and most public APIs cap requests per second, minute or hour, per key or per IP.
- Your own gateway or proxy. Cloudflare rate-limiting rules, AWS API Gateway throttling, nginx
limit_reqand Kong all answer429when a client goes over a limit. - Retry storms. A client that retries immediately on failure multiplies its own traffic and stays over the limit.
- Webhook bursts. A provider replays a backlog or a batch job fires thousands of events at once, and your endpoint (or the API it calls) rate-limits them.
How to fix a 429 as a client
- Honour
Retry-After. It's either seconds (Retry-After: 30) or an HTTP date. Don't send the request again before then. - Back off exponentially with jitter when there's no header: wait 1s, 2s, 4s, 8s… plus a random offset so many clients don't retry in lockstep. See exponential backoff.
- Read the rate-limit headers. Many APIs send
X-RateLimit-RemainingandX-RateLimit-Reset(or the standardRateLimit/RateLimit-Policyheaders) so you can slow down before you hit 429. - Batch and cache. Fewer, larger requests and cached responses use less of your quota.
- Ask for a higher limit if your steady-state traffic is legitimately above it.
429s on a webhook endpoint
When your webhook receiver answers 429, most providers count it as a failed delivery and retry. That's good for durability, but the retries land on an endpoint that's already over its limit. Raising the limit only moves the problem downstream to your database or the API your handler calls.
The usual fix is to put a buffer between the sender and your endpoint and release events at a pace the endpoint can handle. With Webhook Relay outbound throttling, you set a rate (for example 10 requests per second) or a maximum concurrency per destination. A burst of 5,000 events turns into a steady stream, nothing is dropped, and events are delivered oldest first. If the destination still fails, durable retries keep trying with backoff for up to 30 days.
When to return 429 from your own API
Return 429 (not 503 or 400) when a specific client is over its quota, and include Retry-After. Use 503 Service Unavailable when the whole service is overloaded or down for everyone.
