API Rate Limiting and Throttling in Express
Rate limiting protects your API from abuse. Here is how to do it in Express.
API Rate Limiting and Throttling in Express
Rate limiting protects your API from abuse, brute force, and accidental floods. Here is how to do it in Express.
Install
npm install express-rate-limit.
Global Limiter
Apply to all routes:
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // 100 requests per window per IP
standardHeaders: true,
legacyHeaders: false,
message: { error: 'Too many requests, please try again later' }
});
app.use(limiter);
Stricter Limiter on Auth Routes
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5, // 5 attempts per 15 minutes
message: { error: 'Too many login attempts, please try again later' }
});
router.post('/login', authLimiter, login);
router.post('/signup', authLimiter, signup);
Per-User Limiter (After Auth)
const userLimiter = rateLimit({
windowMs: 60 * 60 * 1000, // 1 hour
max: 100,
keyGenerator: (req) => req.user.id
});
router.use('/api', auth, userLimiter);
Store for Distributed Setups
By default, express-rate-limit uses in-memory store. In a cluster or multiple instances, use a shared store like Redis:
const RedisStore = require('rate-limit-redis');
limiter.store = new RedisStore({ client: redisClient });
429 Status Code
Rate-limited requests return 429 Too Many Requests. Include Retry-After header so clients know how long to wait.
Use Cases
- Global: prevent any single IP from flooding your API.
- Auth routes: prevent brute-force password attacks.
- Per-user: prevent a single user from overusing resources.
- Expensive endpoints: stricter limit on endpoints that do heavy work (e.g., report generation).
Beyond IP
IP-based rate limiting can be bypassed by attackers with many IPs. For sensitive endpoints, combine IP-based with user-based and add CAPTCHA for repeated failures.
The Takeaway
Rate limit your Express API with express-rate-limit. Use a global limiter (100 req per 15 min), a stricter limiter on auth routes (5 per 15 min), and per-user limiters for sensitive endpoints. Return 429 with Retry-After. Use Redis for distributed setups.
Use express-rate-limit. Add a global limiter (100 req per 15 min per IP) and stricter limiters on auth routes (5 per 15 min). Return 429 with a Retry-After header. Use a Redis store for distributed setups so limits work across instances.
429 Too Many Requests. Include a Retry-After header so clients know how long to wait. express-rate-limit sets this automatically when standardHeaders: true.
To prevent brute-force password attacks. A global limit of 100 per 15 min is too loose for login; an attacker can try many passwords. A 5-per-15-min limit on login stops brute force.
By default, express-rate-limit uses in-memory store. In a cluster or multiple instances, each instance has its own counter, so limits are not enforced globally. A Redis store shares counters across instances.
IP-based rate limiting can be bypassed by attackers with many IPs (botnets). For sensitive endpoints, combine IP-based with user-based (after auth) and add CAPTCHA for repeated failures. Rate limiting slows abuse; it does not eliminate it.
Ready to master Node.js completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master Node.js
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

