System Design (50 Qs)•Part 2: Real-World High-Scale Architecture Problems (11 - 25)
Design a Distributed Rate Limiter.
In Simple Words: Protect backend microservices from DDoS attacks, brute-force bots, and resource starvation by enforcing request quota policies (e.g. 100 requests per minute per IP or API key).
Algorithm Comparison:
- Token Bucket (Optimal): Tokens are added to a bucket at a constant refill rate. Requests consume 1 token. Handles traffic bursts gracefully.
- Leaky Bucket: Requests enter a queue and leak out at a strictly fixed constant rate. Smooths out traffic spikes.
- Sliding Window Counter: Hybrid combining fixed window memory efficiency with boundary-spike protection.
lua
-- Production Redis Token Bucket Algorithm executed as an atomic Lua script
-- KEYS[1] = Rate limit key (e.g. "ratelimit:user_123")
-- ARGV[1] = Max capacity, ARGV[2] = Refill rate per sec, ARGV[3] = Current epoch, ARGV[4] = Requested tokens
local key = KEYS[1]
local capacity = tonumber(ARGV[1])
local refill_rate = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local requested = tonumber(ARGV[4])
local data = redis.call('HMGET', key, 'tokens', 'last_updated')
local tokens = tonumber(data[1])
local last_updated = tonumber(data[2])
if not tokens then
tokens = capacity
last_updated = now
else
local delta = math.max(0, now - last_updated)
tokens = math.min(capacity, tokens + delta * refill_rate)
last_updated = now
end
if tokens >= requested then
tokens = tokens - requested
redis.call('HMSET', key, 'tokens', tokens, 'last_updated', last_updated)
redis.call('EXPIRE', key, 3600)
return 1 -- Request Allowed
else
return 0 -- Request Denied (HTTP 429 Too Many Requests)
end