Challenge 1: Explain the Race Condition — Possible Solution ==================================================================== Chapter 4's sliding-window pattern is really TWO separate steps run as separate commands: (1) prune old entries and check the current count (ZREMRANGEBYSCORE + ZCARD), and (2) if under the limit, record the new request (ZADD). Between those two steps, nothing stops another request from running its OWN check in the gap. CONCRETE SCENARIO: suppose the limit is 100 requests, and there are currently 99 recorded in the window. 1. Request A runs ZCARD and sees 99 — under the limit, so it proceeds toward calling ZADD to record itself. 2. Before Request A's ZADD actually runs, Request B ALSO runs ZCARD and ALSO sees 99 — because Request A hasn't recorded its own entry yet, the count still looks like 99 to Request B too. 3. Both Request A and Request B independently concluded "we're under the limit" and both proceed — both get allowed through, even though only ONE of them should have been the 100th (limit-reaching) request and the other should have been rejected as the 101st. Both requests checked the count CORRECTLY at the moment they checked it — the bug isn't in the check itself, it's that the check and the recording aren't a single atomic step, so two requests can both see the same "before" state and both act on it, each unaware the other is doing the exact same thing at the same time. This is a classic check-then-act race condition, and it's exactly why Chapter 10 wraps both steps into one atomic Lua script — with an EVAL, there is no gap between the check and the record for a second request to slip into.