Requests pour into a bucket and wait their turn in a queue. A hole near the bottom lets them out to the server at a fixed rate, however bursty the traffic is, and a request that finds the bucket full is dropped. Below, an attacker joins two ordinary users: watch who is dropped, and who waits, when they share one queue and when each has their own.
Each dot stands for 579 real requests. Time is not scaled. At 1x speed the first drop comes about 5.0 s after the first request reaches the bucket, which is the fill time the formula below predicts.
Busiest hour vs the daily average. The book's estimate uses 2x.
The longest a request may sit in a full queue before it is served.
1. Average requests per second
2. Peak requests per second
3. Leak rate r
4. Queue size b
5. What is arriving right now
Doubling DAU doubles the traffic, and because r and b are sized from that same traffic, it doubles them too. Every ratio stays the same, so the queue behaves identically and only the number each dot stands for changes. What changes the behaviour is traffic relative to r: the peak factor, the longest wait, and the attack.
Steps 1 and 2 are the estimation method from the back-of-the-envelope chapter of Alex Xu's System Design Interview, Vol. 1, including its 2x peak. Queue size and outflow rate are the two leaky bucket parameters from its rate limiter chapter. The book does not give a single formula joining them; steps 3 to 5 are that join, written here. Sizing the queue from the longest acceptable wait follows from how a queue works: the last request in a full one is b / r seconds from the front.
The name covers two slightly different designs, and these two examples show both.
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; and limit_req zone=one burst=5;, the rate is the leak rate r, the burst is the queue size b, and the key is the client's IP address, so it is a queue per client. Extra requests are delayed while they wait, and refused once the queue is full, with a 503 by default (limit_req_status changes it). Adding nodelay serves queued requests at once instead of spacing them out, which in effect makes it behave like a token bucket. The documentation's own example also stacks a per-IP limit and a per-server limit, the layered setup described above.Both are the projects' own documentation (primary sources). Quoted sentences are short attributed quotations; the configuration lines are NGINX's own example. Limits change, so check the pages for current values.