API Rate Limiting & Throttling
Rate limiting is the practice of limiting the number of requests a user can make to your API within a specific timeframe (e.g., 100 requests every 15 minutes). This is crucial for protecting your server from abuse, preventing brute-force attacks, and managing costs when using third-party APIs.
1. Why do we need Rate Limiting?โ
- Prevent Abuse: Stop bots from "scraping" all your course data from CodeHarborHub.
- Brute Force Protection: Prevent hackers from trying millions of passwords on your login route.
- Cost Management: If you use paid third-party APIs (like OpenAI), rate limiting saves you from huge bills.
- Server Stability: Ensures that one heavy user doesn't slow down the experience for the "Masters" using your site.
2. Rate Limiting vs. Throttlingโ
While often used interchangeably, there is a slight difference:
- Rate Limiting: Hard limit. Once you hit the limit, you get an error (429 Too Many Requests).
- Throttling: Soft limit. The server slows down your connection speed instead of blocking you entirely.
3. Implementing Rate Limiting in Node.jsโ
We use the popular express-rate-limit package to handle this easily.
Installationโ
npm install express-rate-limit
Basic Setupโ
You can apply a global limit to your entire API:
const rateLimit = require('express-rate-limit');
const globalLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per windowMs
message: {
status: 429,
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 requests
app.use('/api/', globalLimiter);
4. Tiered Rate Limitingโ
As a "Master" architect, you shouldn't treat all routes equally.
Example Strategy:โ
- Login/Signup: Very strict (e.g., 5 attempts per hour) to prevent hacking.
- Search/Courses: Medium (e.g., 100 requests per 15 minutes).
- Public Landing Page: Very loose or no limit.
const authLimiter = rateLimit({
windowMs: 60 * 60 * 1000, // 1 hour
max: 5,
message: "Too many login attempts. Take a break!"
});
app.use('/api/auth/login', authLimiter);
5. Handling the "429 Too Many Requests"โ
When a user hits the limit, your API should return a 429 status code. It is also a best practice to include a Retry-After header telling the client exactly how many seconds to wait before trying again.
6. Using Redis for Scalabilityโ
In a professional "Master" setup with multiple servers, express-rate-limit (which stores data in RAM) won't work well because different servers won't know about each other's limits.
The Pro Solution: Use Redis as a central store for rate-limit data. This way, if a user hits Server A or Server B, their total count is tracked in one place.
Practice: The Stress Testโ
- Apply a limit of 5 requests per minute to your project.
- Open your browser and refresh the page 6 times quickly.
- Did you see your custom error message?
- Check the "Network" tab in your DevToolsโcan you see the
RateLimit-LimitandRateLimit-Remainingheaders?
Always provide a "Whitelist" for your own IP address or internal services (like your monitoring tools) so you don't accidentally lock yourself out of your own API!