JAVASCRIPT
Implement API Rate Limiting with Redis and Express
Protect your Node.js Express API from abuse and brute-force attacks by implementing effective rate limiting using Redis for tracking request counts.
const express = require('express');
const redis = require('redis');
const app = express();
const PORT = 3000;
// Connect to Redis globally and reuse the client
const redisClient = redis.createClient({ url: 'redis://localhost:6379' }); // Use URL for connection
redisClient.on('connect', () => console.log('Connected to Redis!'));
redisClient.on('error', (err) => console.log('Redis Client Error', err));
async function connectRedis() {
if (!redisClient.isOpen) {
await redisClient.connect();
}
}
connectRedis(); // Connect on server startup
const RATE_LIMIT_WINDOW_SECONDS = 60; // 1 minute
const MAX_REQUESTS_PER_WINDOW = 5; // 5 requests
async function rateLimiter(req, res, next) {
const ip = req.ip; // Or req.headers['x-forwarded-for'] for proxied requests
const key = `rate_limit:${ip}`;
try {
// Use the already connected redisClient
const requests = await redisClient.incr(key);
if (requests === 1) {
// Set expiry only for the first request in the window
await redisClient.expire(key, RATE_LIMIT_WINDOW_SECONDS);
}
if (requests > MAX_REQUESTS_PER_WINDOW) {
return res.status(429).json({ message: 'Too many requests, please try again later.' });
}
next();
} catch (error) {
console.error('Rate Limiter Error:', error);
next(error); // Pass error to Express error handler
}
}
app.use(express.json());
app.use(rateLimiter); // Apply rate limiting to all routes
app.get('/api/data', (req, res) => {
res.json({ message: 'This is some protected data.' });
});
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
How it works: This Node.js Express snippet demonstrates API rate limiting using Redis. It assigns a unique key (typically based on the client's IP address) for each client and tracks the number of requests within a defined time window. Redis's `incr` and `expire` commands are used efficiently to count requests and automatically reset the count. If a client exceeds the `MAX_REQUESTS_PER_WINDOW` limit, subsequent requests are blocked with a `429 Too Many Requests` status, protecting the API from brute-force attacks, denial-of-service attempts, and resource exhaustion.