Hello! Welcome to your next lesson in the "Foundational Design Problems" module.
In our last lesson, we designed a complete URL shortening service. We created a public-facing API endpoint POST /urls that anyone could use. This opens up a critical vulnerability: what stops a malicious actor or a buggy client from flooding our service with millions of requests, overwhelming our servers and database? The answer is rate limiting.
This lesson builds directly on that scenario. Your learning outcome is to compare rate limiting algorithms (token bucket, leaky bucket, sliding window) and their trade-offs. Understanding these algorithms is crucial for any senior engineer, as rate limiting is a fundamental requirement for building robust, scalable, and fair distributed systems.
We will cover:
- The purpose of rate limiting and where it fits in a system's architecture.
- A detailed breakdown of the most common rate limiting algorithms.
- A direct comparison of their trade-offs in terms of performance, accuracy, and complexity.
- Key considerations for implementing rate limiting in a distributed environment.
1. What is a Rate Limiter and Where Does it Go?
A rate limiter is a control mechanism designed to cap how many times a user or client can access a resource within a given time frame. Its primary goals are to:
- Prevent abuse from malicious actors (e.g., DoS attacks, credential stuffing).
- Ensure fair usage so that no single user can monopolize system resources.
- Protect backend services from being overwhelmed by sudden traffic spikes.
- Manage costs by controlling usage of paid third-party APIs.
Before we dive into how a rate limiter works, let's discuss where it lives. In a modern backend architecture, you wouldn't typically build this logic into every single microservice. Instead, it's usually handled at a central ingress point.
Design a Rate Limiter Ex-Google SWE | Systems Design Interview Problem
This video from Sanket Singh, an ex-Google engineer, explains the common architectural placements for a rate limiter and why one is strongly preferred.
Watch from 07:35 to 13:03. Pay close attention to the discussion of placing the rate limiter on the client, on the server, and as a middleware/API Gateway. Understand why the API Gateway is the standard location for this functionality in a microservices architecture.
As the video explains, placing the rate limiter in a middleware layer, such as an API Gateway, is the most effective approach. The API Gateway acts as a single entry point for all incoming traffic, making it the perfect choke point to enforce cross-cutting concerns like authentication, logging, and, of course, rate limiting.
2. Core Rate Limiting Algorithms
Now, let's get to the heart of the matter: the algorithms that power the rate limiter. We'll explore four main approaches, each with distinct characteristics and trade-offs.
Five Rate Limiting Algorithms ~ Key Concepts in System Design
This video from 'Hello Byte' provides a clear, analogy-driven explanation of the most common rate limiting algorithms. It's a great way to build intuition for each one.
Watch from 01:16 to 16:43. As you watch, focus on understanding the core mechanism, pros, and cons of each of the following algorithms: Leaky Bucket (01:16): Notice how it smooths out bursts into a constant-rate outflow. Token Bucket (03:45): Contrast this with the leaky bucket. How does it allow for controlled bursts of traffic? Fixed Window Counter (06:39): Understand its simplicity but also its critical flaw at the window boundaries. Sliding Window Log (11:06): See how it solves the fixed window problem with perfect accuracy, but at what cost? Sliding Window Counter (13:47): This is a hybrid. Understand the formula it uses to approximate the rate without storing all timestamps.
To reinforce what you've just seen, let's review the same algorithms in a concise text format. This will help solidify the key concepts and prepare you for the comparison.
Configurable Rate Limiting Rules and Algorithms
This article from 'Hello Interview' provides a clear, text-based explanation of the four most common algorithms used in production systems.
Read the section '2) The system should limit requests based on configurable rules'. This covers the Fixed Window Counter, Sliding Window Log, Sliding Window Counter, and Token Bucket algorithms. Compare these descriptions with what you learned from the video.
Here is a great visual summary of the algorithms we've discussed. Keep these mental models in mind as we move to the comparison.

3. Comparison and Trade-offs: Making the Right Choice
In a system design interview, simply listing the algorithms is not enough. A senior engineer is expected to analyze the trade-offs and justify their choice based on the system's requirements.
This is where we synthesize our knowledge.
Rate Limiting Algorithms Comparison
The 'System Design Sandbox' article provides an excellent comparison table that summarizes the trade-offs we need to consider.
Focus on the 'Comparison Table' section. Study the table carefully, paying attention to how each algorithm scores on memory usage, accuracy, burst handling, and complexity.
Let's break down the key trade-offs from the table:
| Aspect | Fixed Window Counter | Sliding Window Log | Sliding Window Counter | Token Bucket |
|---|---|---|---|---|
| Memory | Very Low | High | Low | Low |
| Accuracy | Approximate | Exact | Good Approximation | Exact |
| Burst Handling | Allows up to 2x burst | No bursts allowed | Smooths bursts | Allows controlled bursts |
| Complexity | Simple | Moderate | Moderate | Moderate |
| Best For | Simple use cases | Strict, low-volume limits | Most APIs (good default) | APIs needing burst tolerance |
Key Interview Takeaways:
- Fixed Window Counter is too inaccurate for most production systems due to the boundary issue, but it's good to mention as a starting point.
- Sliding Window Log is perfectly accurate but uses too much memory to be practical for high-traffic systems.
- Sliding Window Counter is often the best default choice. It offers a great balance of accuracy and low memory usage, effectively smoothing out traffic.
- Token Bucket is also an excellent choice, especially when you want to allow clients to have occasional bursts of traffic (e.g., an API client that processes jobs in batches) before being throttled to a steady rate. Major APIs from Stripe and AWS use this approach.
In an interview, a strong answer would be to recommend the Sliding Window Counter as a robust general-purpose solution, while also mentioning the Token Bucket as a great alternative if the requirements call for accommodating bursty traffic.
4. Deep Dive: Rate Limiting in a Distributed System
Knowing the theory is one thing; implementing it at scale is another. When you have multiple servers or API gateway instances behind a load balancer, how do you ensure the rate limit is enforced globally? If each instance has its own counter, a user could exceed the total limit by spreading requests across different instances.
The solution is a centralized data store for the counters. Given its high performance and features, Redis is the industry standard for this task.
However, using a shared counter introduces a new problem: race conditions.
Implementing Token Bucket with Redis
Let's return to the 'Hello Interview' article to see how to solve this classic distributed systems problem.
Read from 'For our system, we'll go with the Token Bucket algorithm' to the end of the section. Focus on understanding: Why a centralized store like Redis is necessary. The subtle 'read-modify-write' race condition that can occur. How using Lua scripting in Redis solves this by making the entire rate limiting check an atomic operation.
The ability to identify the race condition and propose a solution like Lua scripting demonstrates a deep understanding of distributed systems—a key differentiator for a senior role. The core idea is to move the logic (read counter, check limit, increment counter) from the application server into the data store itself, which can then guarantee the entire sequence is executed atomically.
Conclusion
You have now explored the fundamental algorithms for rate limiting, a critical component for any scalable and resilient system.
Key Takeaways:
- Rate limiting is essential for protecting your services and ensuring fair usage, and it is typically implemented at the API Gateway.
- There are four main algorithms: Token Bucket, Leaky Bucket, Sliding Window Counter, and Fixed Window Counter.
- The choice of algorithm is a trade-off between accuracy, memory usage, and burst handling.
- Sliding Window Counter is an excellent default for many systems, while Token Bucket is ideal when you need to allow for controlled bursts.
- In a distributed environment, you must use a centralized counter (like Redis) and solve for race conditions using atomic operations (like Redis Lua scripts).
Next Lesson Preview:
In this lesson, we focused on the algorithms themselves. In the next lesson, we will put it all together to design a distributed rate limiter. We will treat it as a full system design problem, covering requirements, high-level architecture, the data model for rules, and how to handle failures, building on the concepts you learned today.