Rate limiting sounds like a two-evening project: a counter, a timestamp, a mutex. This series is what happened when I took it seriously instead — eight phases, five algorithms, four benchmark suites, and one shared test suite that graded every implementation the same way.
The thesis is simple and took a while to appreciate: a component can be correct at every level you can test and still be wrong at a level nothing can see. Along the way, measurement contradicted four things I was confident about, and the test suite turned out to contain two assertions that were themselves wrong.
There is no best rate limiting algorithm here. There is a set of tradeoffs, each with a number attached.
Part 1 — Correct and fast. A fixed window that admits 199 requests in a millisecond against a limit of 100, token buckets, three synchronisation strategies benchmarked, and the benchmark that recommended the wrong thing.
Part 2 — Three copies, three times the limit. Why every algorithm breaks identically the moment you scale horizontally, why nothing reports it, and what atomicity costs once the state lives across a network.
Part 3 — Buying less coordination. Leasing quota in blocks, the point where a bigger lease stops paying, and what to do when the thing you now depend on goes down.