Rate Limiting
Redis Rate Limiting
Implement API rate limiting with Redis to protect your services from abuse. Learn sliding window, token bucket, and fixed window patterns.
Real-World Business Scenario
A public API serves 10,000 developers. Without rate limiting, a single misbehaving client can exhaust server resources and degrade service for everyone. You need to enforce 100 requests per minute per API key, with clear feedback when limits are exceeded. Redis provides atomic counters and expiration to implement this efficiently at scale.
Architecture Diagram
API Request + API Key Header
↓
API Gateway / Middleware
↓ Check Rate Limit
┌──────────────────────────────────┐
│ Redis (Rate Limit Counters) │
│ ┌────────────────────────────┐ │
│ │ ratelimit:{apiKey}:{window} │ │
│ │ Value: request count │ │
│ │ TTL: window duration │ │
│ └────────────────────────────┘ │
└──────────────────────────────────┘
↓ Under Limit → Forward
Backend Service
Key Commands Explained
Performance Analysis
INCR is O(1) — constant time regardless of request volume. Adds ~0.1ms overhead per request.
Fixed window: 1 key per user per window. 10K users × 1 key = 10K keys. Minimal memory footprint.
Sliding window (sorted set): O(log N) per operation. More accurate but slightly higher cost. Good for up to ~1000 requests per window.
Redis handles 100K+ INCR/sec on a single instance — sufficient for most rate limiting needs without clustering.
Common Pitfalls
Fixed Window Boundary Burst: A user can send 100 requests at minute :59 and 100 more at :00, effectively 200 in 2 seconds. Use sliding window or sliding log to prevent this.
Race Condition on INCR + EXPIRE: If EXPIRE fails after INCR, the key persists forever and the counter never resets. Always use MULTI/EXEC or Lua scripts.
Clock Skew in Distributed Systems: If app servers have different clocks, window boundaries differ. Use Redis server time (TIME command) as the source of truth.
Missing Rate Limit Headers: Always return X-RateLimit-Limit, X-RateLimit-Remaining, and Retry-After headers so clients can self-throttle.
Best Practices
Use Lua scripts for atomic check-and-increment to eliminate race conditions.
Implement multiple tiers: per-second burst limit + per-minute sustained limit.
Return HTTP 429 with Retry-After header when limit is exceeded.
Use sliding window for user-facing APIs where fairness matters.
Add rate limit info to response headers on every request, not just rejections.
Consider token bucket for APIs that need to allow short bursts above the average rate.
Runnable Demo
Redis Demo
Click "Step" or "Run All" to execute commands...
▌