DevOps intermediate LIVE DEMO
🚦

Rate Limiting Algorithms

Explore token bucket, sliding window, and leaky bucket algorithms. Watch how rate limiters protect APIs by tracking and throttling request rates in real time.

rate limitingtoken bucketsliding windowapi protectionredis
Interactive Demo

Continue with the guided workspace

Use the paired workspace to connect this guide's mental model with live component state, visible signals, and the outcome each step or scenario is meant to prove.

Mental Model

Rate limiting protects APIs and services from overload by enforcing a threshold on how many requests a client can make in a given timeframe.

Instead of writing custom throttle code inside every microservice, rate limiting is usually implemented as a middleware component in an API Gateway. The gateway inspects incoming client headers (like IP address or API key), evaluates if the client has exceeded their quota using an algorithm like Fixed Window, Sliding Window, or Token Bucket, and either forwards the request to the backend or rejects it immediately.

graph TD
    Client[Clients] -->|GET /api| GW[API Gateway / Rate Limiter]
    GW -->|Query Counter / Key| Cache[(Redis Store)]
    Cache -->|Counter Value| GW
    GW -->|Under Limit: Forward| Server[Backend Server]
    GW -->|Over Limit: Reject| Client

Components and Why They Exist

Clients

Represents the users or external systems making requests to the API. Dispatches API requests. Well-behaved clients should dynamically back off and wait when receiving a rate-limit error. In the demo, observe blue request particles leaving the client node and flowing into the Gateway.

Rate Limiter (API Gateway)

Serves as the first line of defense protecting internal network resources. Tracks request counts per client IP or token, executes rate-limiting algorithms, and returns HTTP 429 errors when thresholds are crossed. In the demo, notice how the limiter allows green particles to pass to the backend, but redirects red overflow particles back to the client.

Backend Servers

Processes the business logic and returns API responses. Handles the actual requests. Because the rate limiter blocks excess traffic, the backend remains protected from sudden traffic spikes or denial-of-service attempts. In the demo, you can see how the backend server remains steady and receives only clean, authorized traffic.

Redis Cache (Distributed Counter)

Provides a fast, centralized store to share rate limiting state across multiple gateway nodes. Stores atomic request counters and expirations. This prevents clients from bypassing local rate limiters by routing requests through different load balancers. In the demo, observe the lookup messages passing between the Gateway and Redis in Step 12 and Step 13.


Edge Cases and Misconceptions

Fixed Window Boundary Bursts

A major flaw in the Fixed Window algorithm is that it reset counters at exact calendar intervals (e.g., at 12:00, 12:01). If a limit is set to 10 requests per minute, a client can send 10 requests at 12:00:59 and another 10 requests at 12:01:01. Both batches are accepted because they belong to separate windows, but the backend is hit with a burst of 20 requests in 2 secondsβ€”double the intended limit.

Sliding Window Log Memory Overhead

The Sliding Window Log algorithm resolves the boundary burst problem by saving a timestamp for every request a client makes. When a new request arrives, it deletes timestamps older than the window (e.g., 1 minute) and counts the remaining logs. While highly accurate, storing every timestamp in memory (usually in a Redis sorted set) consumes massive RAM when scaling to millions of active users.

Distributed Synchronization Race Conditions

In distributed rate limiting, checking a counter value and then incrementing it (GET followed by INCR) is not atomic. If two concurrent requests hit two separate gateway nodes at the same time, both might read the counter under the limit and accept the request, causing the client to bypass the limit. To solve this, systems must use atomic Redis Lua scripts to evaluate and increment the counter in a single, blocking Redis thread.

Common Questions

How does the Fixed Window boundary burst occur?

Fixed Window algorithms divide time into static blocks (e.g., 1-minute windows). Counters are reset at the beginning of each block. If a client concentrates their requests at the end of one window and the beginning of the next, they can double their allowed limit in a short time frame, as the limiter only checks the current window's count.

Why use Redis Lua scripting for distributed rate limiting?

Redis Lua scripts are executed atomically on the Redis server. Instead of making multiple network roundtrips to fetch, increment, and set expirations on keysβ€”which introduces race conditions under high concurrencyβ€”a Lua script runs the entire logic locally on Redis. No other command can run until the script finishes, ensuring absolute correctness.

What is the difference between Sliding Window Log and Sliding Window Counter?

Sliding Window Log stores exact timestamps of every request, which is highly accurate but memory-intensive. Sliding Window Counter optimizes this by storing only the request count of the current window and the previous window, then calculating a weighted average based on the current timestamp (e.g., if we are 30% into the current window, the request count = 70% of last window + 100% of current window). This provides a close approximation with minimal memory overhead.

What are the typical headers returned during a rate limit block?

When a client is throttled, well-designed APIs return an HTTP 429 Too Many Requests status code and include specific headers: - `X-RateLimit-Limit`: The maximum number of allowed requests in the window. - `X-RateLimit-Remaining`: The number of requests left before being blocked. - `Retry-After`: The number of seconds the client must wait before making another request.