17 Rate Limiting
title: Rate Limiting in Node.js REST APIs weight: 27 date: 2026-06-28 lastmod: 2026-06-28 description: Implement rate limiting in Node.js REST APIs using express-rate-limit with per-IP, per-user, and per-endpoint limits, sliding windows, and custom limit responses. tags: [api-development, nodejs]
Rate limiting in Node.js REST APIs prevents abuse by capping request frequency using the express-rate-limit package, supporting per-IP, per-user, and per-endpoint limits with sliding windows and custom error responses.
```mermaid
flowchart TD
A[Incoming Request] --> B[Rate Limiter]
B --> C{Under Limit?}
C -->|Yes| D[Process Request]
C -->|No| E[429 Too Many Requests]
D --> F[Decrement Counter]
D --> G[RateLimit Headers]
E --> H[Retry-After Header]
style A fill:#e1f5fe
style B fill:#fff9c4
style C fill:#c8e6c9
style E fill:#ffcdd2
Rate limiting uses a counter per key (IP address, user ID, or API key) that decrements with each request and resets after a window. The sliding window algorithm provides accurate rate limiting without traffic spikes at window boundaries.
Think of rate limiting like a highway toll booth with a monthly pass. Each pass allows 100 trips per month. When you run out, you must wait for the next month or buy more trips. Different endpoints have different pass types.
Example: Global Rate Limiter
const rateLimit = require('express-rate-limit');
const globalLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100,
standardHeaders: true,
legacyHeaders: false,
message: {
status: 'error',
error: {
code: 'RATE_LIMIT_EXCEEDED',
message: 'Too many requests. Please try again later.'
}
}
});
app.use('/api/', globalLimiter);
Example: Per-Endpoint Rate Limiters
const rateLimit = require('express-rate-limit');
// Strict limiter for auth endpoints
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
message: {
error: 'Too many login attempts. Try again in 15 minutes.'
}
});
// Moderate limiter for general endpoints
const apiLimiter = rateLimit({
windowMs: 60 * 1000,
max: 60,
message: {
error: 'Request limit reached. Slow down.'
}
});
// Generous limiter for read-only endpoints
const readLimiter = rateLimit({
windowMs: 60 * 1000,
max: 120,
message: {
error: 'Too many read requests.'
}
});
app.post('/api/auth/login', authLimiter, loginHandler);
app.get('/api/products', readLimiter, productController.list);
app.use('/api/', apiLimiter);
Example: Custom Key Generator (Per-User)
const rateLimit = require('express-rate-limit');
const userLimiter = rateLimit({
windowMs: 60 * 1000,
max: 30,
keyGenerator: (req) => {
// Use user ID if authenticated, otherwise IP
return req.user ? `user:${req.user.userId}` : `ip:${req.ip}`;
},
handler: (req, res) => {
const retryAfter = Math.ceil(req.rateLimit.resetTime - Date.now()) / 1000;
res.status(429).json({
error: 'Rate limit exceeded',
retryAfter,
limit: req.rateLimit.limit,
remaining: 0
});
}
});
app.get('/api/orders', userLimiter, orderController.list);
Example: Skip Certain IPs
const limiter = rateLimit({
windowMs: 60 * 1000,
max: 100,
skip: (req) => {
// Skip rate limiting for health checks and internal IPs
const internalIPs = ['127.0.0.1', '::1', '10.0.0.0/8'];
return req.path === '/api/health' || internalIPs.includes(req.ip);
}
});
Common Mistakes
- Using only IP-based rate limiting — Users behind shared NAT or VPNs share an IP. Use API keys or user IDs for authenticated endpoints.
- Resetting limits at fixed intervals — When all limits reset at the top of the hour, traffic spikes occur. Sliding windows smooth this out.
- Not returning rate limit headers — Clients need X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset to self-regulate their request rate.
- Rate limiting health check endpoints — Monitoring systems that check health frequently get blocked, triggering false alerts.
- Inconsistent rate limit responses — Some endpoints return a JSON error, others HTML. Standardize the rate limit response format across your API.
Practice Questions
- What is the difference between fixed window and sliding window rate limiting?
- How do you set up per-user rate limiting?
- What headers should a rate-limited response include?
- Why should you skip rate limiting for health check endpoints?
- Challenge: Implement a tiered rate limiting system with three tiers (free: 10 req/min, pro: 100 req/min, enterprise: 1000 req/min). Determine the tier from the API key. Return appropriate rate limit headers.
FAQ
Mini Project
Build a tiered rate limiting system for a subscription-based API. Implement three tiers with different limits, Redis-backed counter store, per-user key generation, rate limit headers, and custom error responses. Add skip logic for health and admin endpoints.
What's Next
Now learn about caching with Redis in Building REST APIs with Node.js.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro