Card 06/ 10
Rate Limits as a Contract: 429, Retry-After and RateLimit Headers
A client cannot respect a limit it cannot see, so responses say what is left and when it resets.
A rate limit caps how many requests one client may make in a period, so one client cannot exhaust the API for everyone. A limit is part of the contract: a request over it gets 429 Too Many Requests with a Retry-After header saying when to try again, and responses can carry headers saying what the limit is and how much is left, so a well-behaved client slows down before it is refused.
HTTP/1.1 429 Too Many Requests
Retry-After: 30
RateLimit-Policy: "default";q=100;w=60
RateLimit: "default";r=0;t=30
Content-Type: application/problem+json
{
"type": "https://api.example.com/problems/rate-limited",
"title": "Too many requests",
"status": 429,
"detail": "The limit is 100 requests per minute. Try again in 30 seconds."
}What goes wrong. Without limits, one client's loop, or one attacker, sends thousands of requests a minute and slows or stops the API for everyone. A request for limit=1000000 items does the same in one call.
The response. 429, defined in RFC 6585, says the client sent too many requests. Retry-After gives the seconds to wait. The body uses the API's usual error format. A 403 or a bare 503 would tell the client nothing about when to return.
The headers. RateLimit-Policy describes the limit, here a quota of 100 per 60-second window, and RateLimit the current state, here 0 remaining and 30 seconds until reset. They come from an IETF draft from the HTTP APIs working group whose syntax has changed between versions; many APIs still send the older convention X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Document whichever the API sends.
The fix, beyond the response. Limit per client, by API key or user, with a separate, stricter limit for expensive operations such as login and search. Cap page sizes and body sizes too.
How to test. Send requests past the limit and check the 429, its headers, and that the limit resets when the headers say.
So publish the limits, return 429 with Retry-After, and send headers that let a client stay under them.
← → move through sections and cards