The race condition
A naive distributed limiter reads the counter, compares it to the limit, then writes the increment. Between the read and the write, another server can do the same. Both see a value under the limit and both allow, so the true count overshoots. This is a classic check then act race.
How Lua fixes it
Redis runs a Lua script as a single atomic step. No other command interleaves while the script executes. By placing the read, the limit check, and the increment inside one script, the entire decision becomes indivisible. Either the request is counted and allowed, or it is rejected, with no window for another caller to slip through.
Why not multiple round trips
- Separate commands cross the network and interleave with other clients.
- A transaction with watch can retry on conflict but adds complexity.
- A single script is one round trip and one atomic decision, which is both correct and fast.
Key idea
A Lua script makes the read check and increment of a distributed limiter one atomic step, closing the check then act race.