Rate limiting
In application and API security, rate limiting is the control that caps how many requests a client may make in a window, so that guessing attacks, enumeration and abuse cost the attacker time. It does not decide whether a request is allowed: it decides how often the question can be asked.
How it works
A limiter counts requests against a key, compares the count to a budget over a time window, and rejects what is over budget, normally with HTTP 429 and a Retry-After header. The two common shapes are a fixed or sliding window, which is simple and bursty at the boundary, and a token or leaky bucket, which smooths bursts because tokens refill at a fixed rate.
The design decision that matters is the key. Limiting by source address counts traffic per network position. Limiting by account counts attempts per victim. Limiting by credential counts attempts per password. Limiting by operation counts expensive work rather than requests. A serious deployment uses several keys at once, and applies them at the edge and again in the application, because an attacker who reaches the application directly bypasses the edge.
What goes wrong
The usual finding is a limiter keyed only on the source address, which is the one key an attacker controls. A distributed credential stuffing run spreads a few attempts across thousands of addresses and never trips it. Password spraying defeats it from the other direction: one password against ten thousand accounts is one attempt per account, which no per-account counter sees either. What catches both is a limit on failures per credential and per tenant, plus a behavioural signal.
Then there is the header trick. If the limiter reads a forwarded-for header that the edge does not overwrite, the attacker sets it and resets their own counter. Limits applied on login but not on password reset, on the web form but not on the mobile endpoint, and on the REST route but not on the GraphQL equivalent are all things we find in the same estate.
Where this shows up in an audit
We measure the limit rather than ask about it: send requests until the endpoint refuses, vary the key we can control, and record where the boundary actually sits. The finding names the endpoint, the key, the observed threshold and what changed when we rotated addresses or accounts. A limiter that returns 429 but still processes the request underneath is reported as absent. This is part of how we probe authentication and API abuse controls.