Overview
Rate limiting protects APIs from abuse, ensures fair usage, and prevents DDoS attacks. Learn multiple strategies and implementations.
Common Strategies
- Token Bucket: Smooth rate limiting with burst support
- Sliding Window: Accurate request counting
- Fixed Window: Simple but prone to burst at boundaries
- Leaky Bucket: Smooth output rate
- Adaptive: Dynamic limits based on server load
Token Bucket Algorithm
interface RateLimiter {
tokens: number
lastRefill: number
maxTokens: number
refillRate: number // tokens per second
}
function isAllowed(limiter: RateLimiter): boolean {
const now = Date.now() / 1000
const timePassed = now - limiter.lastRefill
// Refill tokens
limiter.tokens = Math.min(
limiter.maxTokens,
limiter.tokens + timePassed * limiter.refillRate
)
limiter.lastRefill = now
if (limiter.tokens >= 1) {
limiter.tokens -= 1
return true
}
return false
}
// Usage: 100 requests per second with burst of 200
const limiter: RateLimiter = {
tokens: 200,
lastRefill: Date.now() / 1000,
maxTokens: 200,
refillRate: 100
}
Redis-based Implementation
import redis from 'redis'
const client = redis.createClient()
async function rateLimit(userId: string, limit: number, window: number) {
const key = `ratelimit:${userId}`
const count = await client.incr(key)
if (count === 1) {
await client.expire(key, window)
}
return count <= limit
}
// Express middleware
app.use(async (req, res, next) => {
const allowed = await rateLimit(req.ip, 100, 60)
res.set('X-RateLimit-Limit', '100')
res.set('X-RateLimit-Remaining', String(Math.max(0, 100 - count)))
if (!allowed) {
return res.status(429).json({ error: 'Too many requests' })
}
next()
})
Tiered Rate Limiting
const limits = {
free: { requests: 100, window: 3600 },
pro: { requests: 1000, window: 3600 },
enterprise: { requests: Infinity, window: Infinity }
}
async function checkRateLimit(userId: string, tier: 'free' | 'pro' | 'enterprise') {
const limit = limits[tier]
return rateLimit(userId, limit.requests, limit.window)
}
Well-implemented rate limiting reduces API costs by 40-60% by preventing abuse.