Rate Limiting: Four Algorithms, Honestly Compared
Token bucket, leaky bucket, fixed window, sliding window — one bursty arrival pattern replayed through all four at once, every verdict computed from the real algorithm. Where each one lets a burst through, and what it costs to remember the past.
Concept · Systems. The source ↗
A free, interactive, animated visual explainer of Rate Limiting: Four Algorithms, Honestly Compared — built to be understood, not skimmed.
Questions
- What are the four main rate limiting algorithms?
- Token bucket (a bucket of tokens refilled at a steady rate; each request spends one, and the bucket size sets how big a burst is allowed), leaky bucket (the same admission, but accepted requests leave at a fixed, smoothed rate), fixed window (a counter that resets every N seconds), and sliding window — either a log of every request timestamp (exact but O(N) memory per client) or a counter approximation that keeps just two numbers per client.
- What is the difference between token bucket and leaky bucket?
- Their admission decision is identical — with the same capacity and rate they accept and reject exactly the same requests. The difference is output timing: a token bucket lets an accepted burst pass through instantly, while a leaky bucket paces accepted requests out at a fixed rate. nginx uses the leaky bucket "method" so that, past the burst allowance, "requests are processed at a defined rate."
- Why is the fixed window rate limiting algorithm inaccurate?
- It resets its counter on a fixed clock boundary, so a client can spend its whole allowance at the very end of one window and its whole allowance again at the very start of the next. With a limit of 100 per minute, 100 requests at 0:59 and 100 at 1:01 both pass — 200 requests inside a two-second span, twice the intended rate. That seam burst is the flaw the sliding window algorithms exist to fix.
- What is the sliding window counter algorithm?
- A memory-cheap approximation of a true sliding window. Instead of storing every timestamp, it keeps two counters per client — this window and the previous one — and estimates the rolling-window rate by weighting the previous count by how much of it still overlaps the last N seconds. Cloudflare reported that across 400 million requests from 270,000 sources, only 0.003% were wrongly allowed or limited, with a 6% average difference from the true rate.
- How do you rate limit across many servers?
- Move the counter to a shared store like Redis and make the check-and-increment a single atomic operation — an INCR or a Lua script — so two servers racing on the same key cannot both read a stale count and over-admit. The cheaper, higher-latency alternative is a local bucket per server (each server enforcing its share of the limit) with periodic synchronization, trading exactness for one fewer network hop on the hot path.
Related explainers
- Design a Stream Processor with Exactly-Once
- Design a Distributed Cache
- Back-of-the-Envelope: the Numbers That Design Systems
- Threads, Locks & the Anatomy of a Race
- Consistency, Quorums & CAP
- How to Design a System in 60 Minutes
- Idempotency & the Exactly-Once Illusion
- Design Ad-Click Aggregation (Lambda vs Kappa)