Token bucket — allows bursts while maintaining average rate.
1class TokenBucket {2 constructor(options) {3 this.capacity = options.capacity;4 this.tokens = options.capacity;5 this.refillRate = options.refillRate; // tokens per second6 this.lastRefill = Date.now();7 }89 refill() {10 const now = Date.now();11 const elapsed = (now - this.lastRefill) / 1000;12 this.tokens = Math.min(13 this.capacity,14 this.tokens + elapsed * this.refillRate15 );16 this.lastRefill = now;17 }1819 consume(tokens = 1) {20 this.refill();21 if (this.tokens >= tokens) {22 this.tokens -= tokens;23 return true;24 }25 return false;26 }27}2829// Express middleware30const buckets = new Map();3132app.use((req, res, next) => {33 const ip = req.ip;34 if (!buckets.has(ip)) {35 buckets.set(ip, new TokenBucket({36 capacity: 10,37 refillRate: 1,38 }));39 }4041 const bucket = buckets.get(ip);42 if (!bucket.consume()) {43 return res.status(429).json({ error: "Rate limited" });44 }4546 next();47});
Key points: