Build the mental model
Rate limits track a counter per user, IP, or API key and time window. Separate INCR and EXPIRE calls leave a crash gap, so use a Lua script atomically. Fixed windows are simple but allow boundary bursts; sliding windows or token buckets are smoother but cost more.
Connect it to a real scenario
Limit login requests to ten per 60 seconds for each user-and-IP identity. The script increments the counter, applies expiry on the first request, and returns count and TTL. Return limit, remaining, and retry-after headers to clients.
Try the working example
local count = redis.call('INCR', KEYS[1])
if count == 1 then redis.call('EXPIRE', KEYS[1], ARGV[1]) end
local ttl = redis.call('TTL', KEYS[1])
return {count, ttl}
-- EVALSHA <sha> 1 rl:login:user42:iphash 60The request count and remaining window TTL are returned atomically.5-minute try-it
Design an IP limiter for anonymous search and a user limiter for authenticated exports.
One important caution
Blindly trusting proxy headers lets attackers rotate a claimed IP and bypass the limiter.
Redis — Rate Limiting — Redis