Sliding window — tracks requests within a moving time window.
1const Redis = require("ioredis");2const redis = new Redis();34async function slidingWindowRateLimit(key, limit, windowMs) {5 const now = Date.now();6 const windowStart = now - windowMs;78 const pipeline = redis.pipeline();9 pipeline.zremrangebyscore(key, 0, windowStart);10 pipeline.zadd(key, now, `${now}-${Math.random()}`);11 pipeline.zcard(key);12 pipeline.pexpire(key, windowMs);1314 const results = await pipeline.exec();15 const count = results[2][1];1617 return {18 allowed: count <= limit,19 remaining: Math.max(0, limit - count),20 resetAt: now + windowMs,21 };22}2324// Middleware25async function rateLimitMiddleware(req, res, next) {26 const key = `rate:${req.ip}`;27 const result = await slidingWindowRateLimit(key, 100, 60000);2829 res.setHeader("X-RateLimit-Limit", 100);30 res.setHeader("X-RateLimit-Remaining", result.remaining);31 res.setHeader("X-RateLimit-Reset", result.resetAt);3233 if (!result.allowed) {34 return res.status(429).json({ error: "Too many requests" });35 }36 next();37}
Advantages over fixed window: