hardBackend EngineerSaaS
How would you implement rate limiting in a Node.js Express application to prevent API abuse?
Posted 18/04/2026
by Mehedy Hasan Ador
Question Details
Interview question:
> "Our public API is getting hammered. Some users make 1000 requests per minute. We need to implement rate limiting: 100 req/min for free users, 1000 req/min for paid. How would you architect this?"
> "Our public API is getting hammered. Some users make 1000 requests per minute. We need to implement rate limiting: 100 req/min for free users, 1000 req/min for paid. How would you architect this?"
Suggested Solution
Rate Limiting with Redis + Express
import express from "express";
import Redis from "ioredis";
const redis = new Redis(process.env.REDISURL);
interface RateLimitOptions {
windowMs: number; // Time window in ms
maxRequests: number; // Max requests in window
keyPrefix: string;
}
async function rateLimiter(req: express.Request, res: express.Response, next: express.NextFunction) {
const userId = req.user?.id || req.ip;
const plan = req.user?.plan || "free";
const limits = {
free: { windowMs: 60000, maxRequests: 100 },
paid: { windowMs: 60000, maxRequests: 1000 },
};
const { windowMs, maxRequests } = limits[plan];
const key = rate-limit:${userId}:${plan};
// Sliding window using Redis sorted sets
const now = Date.now();
const windowStart = now - windowMs;
const pipeline = redis.pipeline();
pipeline.zremrangebyscore(key, 0, windowStart); // Remove expired entries
pipeline.zadd(key, now, ${now}-${Math.random()}); // Add current request
pipeline.zcard(key); // Count requests in window
pipeline.pexpire(key, windowMs); // Auto-expire the key
const results = await pipeline.exec();
const requestCount = results?.[2]?.[1] as number;
res.set({
"X-RateLimit-Limit": maxRequests.toString(),
"X-RateLimit-Remaining": Math.max(0, maxRequests - requestCount).toString(),
"X-RateLimit-Reset": new Date(now + windowMs).toISOString(),
});
if (requestCount > maxRequests) {
return res.status(429).json({
error: "Too many requests",
retryAfter: Math.ceil(windowMs / 1000),
});
}
next();
}
Rate Limiting Algorithms
Production Architecture
Client → CDN (Cloudflare rate limit: 10K/min)
→ Load Balancer
→ Express (per-user rate limit via Redis)
→ API Handler
Layer 1: CDN (DDoS protection)
Layer 2: Application (per-user, per-plan limits)
Layer 3: Database (connection pool limits)
Quick Alternative: express-rate-limit
import rateLimit from "express-rate-limit";
import RedisStore from "rate-limit-redis";
const limiter = rateLimit({
store: new RedisStore({ client: redis }),
windowMs: 60000,
max: (req) => req.user?.plan === "paid" ? 1000 : 100,
keyGenerator: (req) => req.user?.id || req.ip,
standardHeaders: true,
legacyHeaders: false,
});
app.use("/api", limiter);