Rate Limiting Algorithms Explained — Complete Comparison Guide
In this tutorial, you will learn about Rate Limiting Algorithms Explained. We cover key concepts, practical examples, and best practices to help you master this topic.
Rate limiting algorithms determine how request counts are tracked and enforced, with each algorithm offering different trade-offs between accuracy, memory usage, and implementation complexity.
What You'll Learn
By the end of this tutorial, you will understand five rate limiting algorithms, their strengths and weaknesses, and when to use each one in your application.
Why It Matters
Choosing the wrong algorithm leads to either inaccurate limiting (letting too many requests through) or excessive resource usage. DodaTech selects algorithms based on each API's specific requirements.
Real-World Use
DodaZIP's conversion API uses the token bucket algorithm for general rate limiting and the Sliding Window algorithm for login attempts, where precision matters most.
Rate Limiting Algorithms Learning Path
flowchart LR
A[Rate Limiting Intro] --> B[Algorithms Overview]
B --> C[Token Bucket]
B --> D[Sliding Window]
B --> E[Fixed Window]
B --> F{You Are Here}
style F fill:#f90,color:#fff
Algorithm Comparison Table
| Algorithm | Accuracy | Memory | Burst Handling | Complexity |
|---|---|---|---|---|
| Token Bucket | Medium | Low | Yes | Low |
| Leaky Bucket | High | Low | No | Low |
| Fixed Window | Low | Low | Yes (at boundaries) | Very Low |
| Sliding Window | High | Medium | Moderate | Medium |
| Sliding Log | Very High | High | Yes | High |
Fixed Window Algorithm
The simplest algorithm: count requests in fixed time Windows (e.g., per minute). It is easy to implement but allows double traffic at window boundaries.
const fixedWindowLimiter = new Map();
function fixedWindow(req, res, next) {
const key = req.ip;
const now = Math.floor(Date.now() / 60000);
const maxReqs = 10;
const mapKey = `${key}:${now}`;
const count = (fixedWindowLimiter.get(mapKey) || 0) + 1;
fixedWindowLimiter.set(mapKey, count);
if (count > maxReqs) {
return res.status(429).json({ error: "Limit exceeded" });
}
next();
}
Expected behavior: 10 requests are allowed per minute, but at the boundary between minutes, a client could make 20 requests in 2 seconds.
Sliding Window Algorithm
Sliding window tracks requests in a rolling time window, providing smoother limits than fixed window by considering the previous window's data.
const slidingWindow = new Map();
function slidingWindowLimiter(req, res, next) {
const key = req.ip;
const windowMs = 60000;
const maxReqs = 10;
const now = Date.now();
if (!slidingWindow.has(key)) {
slidingWindow.set(key, []);
}
const timestamps = slidingWindow.get(key);
const windowStart = now - windowMs;
while (timestamps.length > 0 && timestamps[0] < windowStart) {
timestamps.shift();
}
if (timestamps.length >= maxReqs) {
return res.status(429).json({ error: "Limit exceeded" });
}
timestamps.push(now);
next();
}
Expected behavior: At most 10 requests in any rolling 60-second window. A burst of 10 requests at second 59 blocks further requests until second 119.
Common Mistakes
Not cleaning up expired entries — Fixed window stores grow forever. Set TTLs or purge old entries periodically.
Using fixed window for critical limits — Fixed window allows double traffic at boundaries. Use sliding window for precise limits.
Storing all timestamps for high-traffic endpoints — Sliding log stores every timestamp, consuming memory proportional to traffic volume.
Not handling clock skew in Distributed Systems — Servers with different clocks produce inconsistent results. Use a centralized time source.
Ignoring algorithm overhead — Sliding log with millions of entries is slow. Choose simpler algorithms for high-throughput paths.
Practice Questions
Which algorithm is easiest to implement? Fixed window is the simplest but also the least accurate.
When should you use sliding log over sliding window? When you need exact counts, not approximations. Sliding log records every timestamp.
Why does fixed window allow burst traffic at boundaries? Because the counter resets at the window boundary, a client can use the full limit at the end of one window and again at the start of the next.
Challenge: Implement a rate limiter that uses different algorithms for different endpoints.
app.use("/api/login", slidingWindowLimiter);
app.use("/api/search", fixedWindowLimiter);
app.use("/api/upload", tokenBucketLimiter);
FAQ
Mini Project
Build a configurable rate limiter that supports multiple algorithms and switches between them based on configuration.
function createRateLimiter(algorithm, options) {
switch (algorithm) {
case "fixed-window":
return fixedWindowLimiter(options);
case "sliding-window":
return slidingWindowLimiter(options);
case "token-bucket":
return tokenBucketLimiter(options);
case "leaky-bucket":
return leakyBucketLimiter(options);
default:
throw new Error(`Unknown algorithm: ${algorithm}`);
}
}
const loginLimiter = createRateLimiter("sliding-window", {
windowMs: 900000, max: 5
});
const apiLimiter = createRateLimiter("token-bucket", {
capacity: 100, refillRate: 10, refillInterval: 1000
});
app.use("/login", loginLimiter);
app.use("/api", apiLimiter);
What's Next
Now that you understand rate limiting algorithms, explore implementing the token bucket algorithm in detail. Then learn about the leaky bucket algorithm for traffic shaping.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro