Definition · Token bucketA bucket has a capacity b and refills at r tokens per unit time. Between two arrivals separated by Δt, the level rises by r·Δt and is then capped at b. An arrival is admitted if at least one whole token is present, and it spends one; otherwise it is rejected and the level is unchanged.
Theorem · The bucket's guaranteeOver any window of length t, the number of admissions is at most b + r·t: the tokens that were in the bucket at the start, plus the tokens that arrived during the window.
That bound is the reason a bucket is used at all. It holds for every window — not for aligned windows, not on average — because every admission consumed a token, and the tokens available in an interval are the starting level plus the refill, with the starting level capped at b. With r = 5 a second and b = 3, no second anywhere in any trace carries more than 8 admissions.
trace: 20 arrivals over 2.2 seconds, bunched at 900 ms and 1000 ms
r = 5 tokens / s b = 3
bucket admitted 13, rejected 7
largest second it allowed: 7 (bound is b + r = 8)
fixed window at 5 per second, on the same trace
admitted 12, rejected 8
largest second it allowed: 9 while advertising 5
The two limiters admit almost the same number of requests overall, which is what makes the comparison interesting: they differ in when. The window admitted fewer requests in total and let nine of them through in one second, because the trace was built to straddle a boundary. The bucket's worst second was seven, under its own bound of eight.
What the downstream service sees
The number that matters to whatever sits behind the limiter is the worst second, not the total: it is the one that sets the queue of the previous lessons, and a limiter advertising five that delivers nine has sized the downstream system's headroom incorrectly by a factor of nearly two. A bucket's worst case is b + r·t, which is a number you chose.
Example · Twenty idle seconds buy three tokensWith r = 1 a second and b = 3, a bucket left alone for twenty seconds holds three tokens, not twenty. Seven arrivals at once therefore see three admitted and four refused. The cap is what makes b mean “the burst I am willing to absorb” rather than “whatever has accumulated since the last quiet period”.
Choosing the two parameters is a design conversation with two separate questions in it. r is the sustained rate the downstream system can carry — a capacity question, answered by the earlier courses. b is how much bunching you are willing to pass through in one go, and its cost is paid by the queue behind it: the burst arrives, and everything this course has said about waiting says what that does to it.
Two smaller points worth knowing. Rate limiting is loss, not delay: a rejected request is refused immediately, which is a bounded, honest failure that a client can retry — and retries are exactly the c_a² that the variability lesson warns about, so they want jitter. And a bucket can also be run as a shaper rather than a limiter, holding arrivals until a token appears instead of refusing them, which converts the same bound back into waiting.
Token levels here are exact fractions of a token computed from integer millisecond gaps, not floating-point approximations, so a long trace cannot drift. That matters for a limiter more than for most arithmetic on this course: a drift of a thousandth of a token per arrival is a different limit after a million requests.