Question presented to candidate: "Our API gateways run on 20 machines and every API key gets 100 requests per rolling minute. Build the limiter on Redis. Show me the data structure and the script, and explain why it has to be a Lua script rather than a few Redis commands from the gateway."
What a strong answer should cover:
- Data structure: one sorted set per key, score = request timestamp in ms, member = a unique request id; trim with
ZREMRANGEBYSCORE, count withZCARD, record withZADD, expire withPEXPIRE - Why Lua: the check and the write must be atomic; as separate commands from many gateways it is check-then-act and over-admits. Redis runs a script without interleaving other commands
- Correctness details: members must be unique (two requests in the same ms would collapse), denied requests must not be recorded, compute
Retry-Afterfrom the oldest entry - Operations:
SCRIPT LOAD+EVALSHAwith aNOSCRIPTfallback (or Redis Functions), which clock to trust (client time vsTIME), keys in one hash slot in Redis Cluster - Cost: memory grows with the limit (one entry per allowed request in the window); the sliding window counter variant uses two counters when the log is too big
- Failure policy if Redis is slow or down: fail open or fail closed, with a timeout
Clarifying questions expected:
- Must the limit be exact, or is an approximation within a few percent acceptable?
- How large are the limits (10 per minute or 10,000 per minute), and how many active keys?
- If Redis is unavailable, should requests be allowed or rejected?
Code / implementation expected: Yes โ the Lua script and how the gateway calls it; the example simulates the sorted set to show the race, member collisions and lockout, and the script itself was run on Redis 7.0.15.