Implementing Rate Limiting

1. Implementing Fixed Window Counter

Example: 100 req/min per user

local key = "rate:" .. user .. ":" .. minute
local c = redis.call('INCR', key)
if c == 1 then redis.call('EXPIRE', key, 60) end
return c <= 100
PropertyDetail
MemoryO(users × windows)
IssueBurst at window boundary

2. Implementing Sliding Window Counter

ApproachDetail
HybridCurrent + previous window weighted
Memory2 counters per user
AccuracyGood approximation

3. Using Token Bucket Algorithm

Example: Token bucket via Lua

-- Refill tokens based on elapsed, deduct one
local h = redis.call('HMGET', KEYS[1], 'tokens', 'ts')
local tokens, ts = tonumber(h[1]) or capacity, tonumber(h[2]) or now
tokens = math.min(capacity, tokens + (now - ts) * rate)
if tokens < 1 then return 0 end
redis.call('HMSET', KEYS[1], 'tokens', tokens - 1, 'ts', now)
redis.call('EXPIRE', KEYS[1], 3600)
return 1

4. Using Sorted Sets for Sliding Windows

StepCommand
Add requestZADD key now now
Drop expiredZREMRANGEBYSCORE key -inf (now-window)
CountZCARD key
Expire keyEXPIRE key window

5. Using Sliding Window Log Algorithm

PropertyTradeoff
PrecisionExact
MemoryO(allowed_requests) per user

6. Implementing Leaky Bucket Pattern

AspectDetail
BehaviorQueue drains at constant rate
StorageHash with depth + last leak time

7. Setting Rate Limit Expiration

StrategyDetail
TTL = windowAuto-cleanup; use EXPIRE on key creation

8. Implementing Distributed Rate Limiting

ApproachNotes
Central RedisAll app nodes share counter — strongest consistency
Cluster + hashtag{rate}:user:42 pins all keys to one slot

9. Handling Race Conditions

RiskMitigation
Increment + check raceWrap in Lua for atomicity
TTL set raceConditional EXPIRE only when counter=1

10. Optimizing with Lua Scripts

BenefitDetail
One RTTSingle EVALSHA replaces multiple commands
AtomicNo interleaving from other clients