Rate Limiting & Slowing Down Responses
Imagine a stadium with only one entrance. If thousands of people try to enter at once, chaos ensues some might get crushed, and security can't check everyone properly. Rate limiting is like having a turnstile that only lets a certain number of people through per minute. It protects your server from being overwhelmed by too many requests.
What is Rate Limiting?
Rate limiting is a technique to control the number of requests a client can make to your API within a specific time window. It's essential for:
- Preventing brute force attacks on login endpoints
- Protecting against DDoS attacks
- Ensuring fair usage of your API
- Preventing server overload
- Avoiding excessive costs (if using paid services)
Implementing Rate Limiting with express-rate-limit
The most popular rate limiting middleware for Express is
express-rate-limit.npm install express-rate-limitconst rateLimit = require('express-rate-limit');
// Create a limiter: max 100 requests per 15 minutes
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP, please try again later.',
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
});
// Apply to all routes
app.use(limiter);Different Limits for Different Routes
You might want stricter limits on sensitive routes like login.
// Strict limiter for login - 5 attempts per 15 minutes
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
message: 'Too many login attempts, please try again after 15 minutes',
skipSuccessfulRequests: true, // Don't count successful logins
});
// Apply only to login route
app.post('/login', loginLimiter, (req, res) => {
// your login logic
});
// General limiter for other routes
app.use('/api', limiter);Customizing Rate Limit Behavior
const customLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 10,
message: {
success: false,
error: 'Rate limit exceeded. Please slow down.'
},
statusCode: 429, // Too Many Requests
keyGenerator: (req) => {
// Use user ID if authenticated, otherwise IP
return req.user?.id || req.ip;
},
handler: (req, res) => {
// Custom response when limit is exceeded
res.status(429).json({
error: 'Rate limit exceeded',
retryAfter: Math.ceil(req.rateLimit.resetTime / 1000)
});
}
});Slowing Down Responses
Sometimes instead of blocking requests, you might want to slow them down. This can be useful for preventing brute force attacks while maintaining a better user experience.
Using express-slow-down
npm install express-slow-downconst slowDown = require('express-slow-down');
const speedLimiter = slowDown({
windowMs: 15 * 60 * 1000, // 15 minutes
delayAfter: 10, // Allow 10 requests without delay
delayMs: 500, // Then add 500ms delay per request above limit
maxDelayMs: 5000, // Maximum delay of 5 seconds
});
app.use('/api', speedLimiter);Combining Rate Limiting and Slowing Down
// First slow down, then eventually block
app.post('/login',
slowDown({
windowMs: 15 * 60 * 1000,
delayAfter: 3,
delayMs: 1000
}),
rateLimit({
windowMs: 15 * 60 * 1000,
max: 10
}),
(req, res) => {
// login logic
}
);Rate Limiting with Redis for Distributed Systems
If your app runs on multiple servers, in-memory rate limiting won't work across servers. Use Redis for distributed rate limiting.
npm install rate-limit-redis redisconst RedisStore = require('rate-limit-redis');
const redis = require('redis');
const redisClient = redis.createClient();
const limiter = rateLimit({
store: new RedisStore({
client: redisClient,
prefix: 'rl:',
}),
windowMs: 15 * 60 * 1000,
max: 100
});Best Practices
- Apply stricter limits on authentication routes Prevent brute force attacks.
- Use different limits for different user roles Anonymous users get stricter limits than authenticated users.
- Return appropriate headers Let clients know their rate limit status.
- Log rate limit violations Monitor for potential attacks.
- Use Redis for multi-server deployments Ensure limits work across instances.
- Consider using a CDN or API gateway For enterprise-level rate limiting.
Two Minute Drill
- Rate limiting prevents abuse by limiting requests per time window.
- Use
express-rate-limitfor basic rate limiting. - Apply stricter limits on login/registration routes.
- Use
express-slow-downto gradually delay responses instead of blocking. - For distributed systems, use Redis-based rate limiting.
- Rate limiting is essential for security and API stability.
Need more clarification?
Drop us an email at career@quipoinfotech.com
