Glossary
Rate limiting
Rate limiting caps how many requests a client may make in a period, refusing the excess. It protects capacity against accidental overload and protects specific endpoints against abuse — a login form being guessed, a password reset being used to send mail, an expensive search being called in a loop. The correct refusal is `429 Too Many Requests`, ideally with a `Retry-After` header so the client knows when to return.
The common algorithms
Fixed window: count requests per calendar minute and reset. Simple, and it allows a burst of double the limit across a window boundary.
Sliding window: count over the trailing period, which removes the boundary burst at the cost of more state.
Token bucket: tokens accumulate at a fixed rate up to a ceiling, and each request spends one. It permits a controlled burst followed by a steady rate, which matches how real clients behave.
Leaky bucket: requests drain at a fixed rate, smoothing bursts entirely.
The choice matters less than picking a key: per address, per account, per API key, or a combination. A limit keyed only on address penalises shared networks and misses distributed abuse.
The response headers
`429 Too Many Requests` is the status code for a refusal due to rate limiting. Returning 403 instead is common and tells the client nothing useful.
`Retry-After` states when to come back, as seconds or an HTTP date. Without it a client guesses, usually badly.
`RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` advertise the policy on every response, letting a well-behaved client pace itself instead of discovering the limit by hitting it.
Advertising the policy is a courtesy to integrators and a small disclosure to everyone else, which is a trade-off most public APIs resolve in favour of publishing it.
What it defends and what it does not
It defends against volume from a client you can identify: a runaway script, a scraper, credential guessing from one source.
It does not defend against a distributed attack, where each participant stays under the limit. That needs traffic analysis, not counting.
It does not defend against a single expensive request. An endpoint that takes ten seconds of database time is a capacity problem a rate limit barely touches.
Applied to authentication, it is one of the more effective controls available — guessing passwords is useless at three attempts a minute.
How to check it from outside
Look for `RateLimit-*` headers on ordinary responses. Their absence does not mean no limit exists; many are enforced without advertising.
Repeated rapid requests eventually produce a 429 or a 403 if a limit is enforced — a test worth running only against systems you operate.
Check that authentication endpoints specifically are limited, since that is where the return on the control is highest.
Check that the refusal is a 429 rather than a 403, and that it carries `Retry-After`.
Frequently asked questions
- Which status code should a rate limit return?
- 429 Too Many Requests, with a Retry-After header. Returning 403 is common and gives the client no way to behave correctly.
- Does rate limiting stop a distributed attack?
- No. Each participant stays below the limit. Distributed traffic needs analysis and filtering rather than per-client counting.
- Should I publish my rate limits in headers?
- For an API with integrators, yes — it lets clients pace themselves. It is a small disclosure, and most public APIs judge it worthwhile.
Sources
Related
VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.
Scan a website