Expand description
Rate limiting on top of the Cache trait.
§Fixed window, and what that costs
A counter is kept per window: the key embeds now / window, so at every
boundary the counter is a new key that starts at zero and expires on its own.
One increment per request, one key per window, nothing to clean up.
The price is burstiness at the seam. With a limit of 60 per minute, a client can send 60 requests in the last instant of one window and 60 in the first instant of the next — 120 in a moment, twice the nominal rate. A sliding window (a sorted set of timestamps, or a weighted blend of the current and previous window) removes that, at the cost of storing a timestamp per request or of a second read on every request.
Fixed window is the right default here because the job of a throttle
middleware is to stop abuse and runaway clients, and a 2× burst for one
instant does not defeat that — while the sorted-set approach makes every
request more expensive for every honest user. Anything that genuinely needs
a smooth rate (billing, an upstream API quota) should be built on
RateLimiter::attempt’s reported window rather than pretending the
boundary does not exist.
§Which driver
The limiter is only as shared as its cache. The memory driver counts per process, so four workers behind a load balancer allow four times the limit; use the Redis driver whenever more than one process serves traffic.
Structs§
- Rate
Limit - The outcome of one attempt, and everything the
X-RateLimit-*headers need. - Rate
Limiter - Counts attempts per key and window against any
Cache.