What is Rate Limiting?
Download this article as a PDF on the Codeflare Mobile App
Rate limiting restricts the number of requests a client can make within a specific time window.
Example:
- Max: 100 requests per 15 minutes per IP
- If exceeded → request is blocked (usually with
429 Too Many Requests)
Why it matters:
- Prevents brute-force attacks
- Stops API abuse
- Protects server resources
- Ensures fair usage across users
What is Throttling?
Throttling controls the rate at which requests are processed, often by slowing them down rather than blocking them outright.
Learn on the Go. Download the Codeflare Mobile App from Google Play Store
Example:
- Allow 1 request per second
- Extra requests are delayed or queued
Key difference:
| Feature | Rate Limiting | Throttling |
|---|---|---|
| Behavior | Blocks excess requests | Slows them down |
| Response | 429 error | Delayed response |
| Use case | Security & abuse control | Traffic shaping & smoothing |
Core Algorithms Behind Rate Limiting
Understanding these helps you design custom systems.
1. Fixed Window Counter
- Count requests in a fixed time window (e.g., per minute)
- Simple but can cause bursts
👉 Problem: A user can send many requests at the boundary
2. Sliding Window Log
- Stores timestamps of requests
- More accurate but memory-heavy
3. Sliding Window Counter
- Hybrid approach (more efficient than logs)
4. Token Bucket (Best for Throttling)
- Tokens are added at a steady rate
- Requests consume tokens
- If no tokens → wait or reject
5. Leaky Bucket
- Requests are processed at a fixed rate
- Excess requests are queued or dropped
Implementing Rate Limiting in Node.js
1. Using express-rate-limit (Most Common)
Install:
npm install express-rate-limit
Basic Setup:
const express = require('express');
const rateLimit = require('express-rate-limit');
const app = express();
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP
message: 'Too many requests, try again later',
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api', limiter);
app.get('/api/data', (req, res) => {
res.send('API response');
});
app.listen(3000);
2. Advanced Rate Limiting with Redis (Production Ready)
For distributed systems (multiple servers), in-memory limits won’t work.
Use Redis.
Install:
npm install rate-limiter-flexible ioredis
Example:
const { RateLimiterRedis } = require('rate-limiter-flexible');
const Redis = require('ioredis');
const redisClient = new Redis();
const rateLimiter = new RateLimiterRedis({
storeClient: redisClient,
points: 10, // 10 requests
duration: 1, // per second
});
const express = require('express');
const app = express();
app.use(async (req, res, next) => {
try {
await rateLimiter.consume(req.ip);
next();
} catch {
res.status(429).send('Too Many Requests');
}
});
3. Implementing Throttling (Custom Logic)
Simple Delay Throttling:
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
app.use(async (req, res, next) => {
await delay(500); // delay each request
next();
});
4. Token Bucket Example
class TokenBucket {
constructor(capacity, refillRate) {
this.capacity = capacity;
this.tokens = capacity;
this.refillRate = refillRate;
this.lastRefill = Date.now();
}
refill() {
const now = Date.now();
const diff = (now - this.lastRefill) / 1000;
this.tokens = Math.min(this.capacity, this.tokens + diff * this.refillRate);
this.lastRefill = now;
}
consume() {
this.refill();
if (this.tokens >= 1) {
this.tokens -= 1;
return true;
}
return false;
}
}
Best Practices for Node.js Apps
1. Use IP + User-Based Limiting
- Combine IP + API key / user ID
- Prevent shared IP abuse
2. Different Limits per Route
app.use('/login', strictLimiter);
app.use('/api', generalLimiter);
3. Protect Sensitive Endpoints
- Login
- Password reset
- Payment APIs
4. Use Headers for Transparency
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 20
5. Graceful Handling
Return helpful errors:
{
"error": "Too many requests",
"retry_after": "60 seconds"
}
6. Combine with Other Security Layers
- CAPTCHA
- API keys
- Authentication (JWT)
- WAF (Cloudflare in for apps like Codeflare)
Real-World Use Cases
1. Login Protection
- 5 attempts per minute
- Prevent brute-force attacks
2. Public APIs
- Free tier: 100 requests/hour
- Paid tier: 1000 requests/hour
3. Payment Systems
- Strict throttling to prevent fraud spikes
4. Scraping Prevention
- Detect unusual request bursts
⚠️ Common Pitfalls
- ❌ Using in-memory limiter in distributed apps
- ❌ Not handling proxies (
X-Forwarded-For) - ❌ Blocking legitimate users (too strict limits)
- ❌ Ignoring burst traffic patterns
Conclusion
- Rate limiting = control how many requests are allowed
- Throttling = control how fast requests are processed
- Both are critical for:
- Security
- Performance
- Scalability

Latest tech news and coding tips.