Concept lesson

Rate Limiting & Thundering Herd Defense

Token Bucket, Leaky Bucket, and Redis sliding-window rate limiting algorithms.

lesson
Freshness: current15 min read
Mastery
not started · 0%

Learning outcomes

  • Build distributed rate limiting using Redis atomic scripts
  • Protect downstream APIs from traffic spikes and abuse

Mental model

Rate limiting regulates the frequency of client API requests to protect server infrastructure, prevent Denial-of-Service (DoS) overloads, and enforce API monetization tiers.

Incoming Client HTTP Request
Extract Client IP / API Key
Execute Redis Sliding-Window Script
Evaluate Request Count vs Limit
Return 200 OK or 429 Too Many Requests
Conceptual teaching model synthesized from:FastAPI Framework Architecture & Dependency Injection Specification

Theory

  • Token Bucket: Refills tokens at a constant rate; permits burst traffic up to bucket capacity.
  • Leaky Bucket: Queues requests and processes them at a strict constant output rate; smooths out bursts.
  • Fixed Window Counter: Counts requests per fixed minute/hour window; vulnerable to double-limit traffic spikes at window boundaries.
  • Sliding Window Log / Counter: Measures requests over a moving time window; highly accurate.
# Redis Sliding-Window Rate Limiter in Python
import time
import redis.asyncio as aioredis

redis = aioredis.from_url("redis://localhost:6379")

async def is_rate_limited(user_id: str, limit: int = 100, window_seconds: int = 60) -> bool:
    now = time.time()
    clear_before = now - window_seconds
    key = f"rate:{user_id}"
    
    async with redis.pipeline(transaction=True) as pipe:
        pipe.zremrangebyscore(key, 0, clear_before)
        pipe.zadd(key, {str(now): now})
        pipe.zcard(key)
        pipe.expire(key, window_seconds)
        results = await pipe.execute()
        
    request_count = results[2]
    return request_count > limit

Alternatives and trade-offs

  • Fixed Window: Minimal memory footprint; allows 2x limit spikes near window resets.
  • Sliding Window Log (Redis ZSET): 100% boundary accuracy; higher Redis RAM usage for high request volumes.
  • Token Bucket: Supports legitimate burst traffic while maintaining average rate limits.

Failure modes and misconceptions

  1. Non-Atomic Rate Limit Checks: Executing GET count followed by SET count in separate non-atomic commands causes race conditions under high concurrency. Always use Redis Lua scripts or MULTI/EXEC pipelines.
  2. Missing Retry-After Headers: Returning HTTP 429 Too Many Requests without an explicit Retry-After header causes aggressive client retries.
Reflect before revealing the guide

Decision scenario

Use Redis Sliding Window rate limiting for API Gateway authentication tiers to enforce accurate client rate limits without window boundary traffic spikes.

Learning outcomes

  • Implement Token Bucket, Leaky Bucket, and Sliding Window rate limiting algorithms.
  • Execute atomic rate limit calculations using Redis pipelines and Lua scripts.
  • Attach standard HTTP rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After).

Trade-offs

Rate limiting guarantees API availability and protection against abuse, but requires fast in-memory stores like Redis for distributed state tracking.

Evidence assessment

Theory and decision mastery

not-started · 0%
theory0%
decision0%
activityNot mapped
projectNot mapped
1. What is the core architectural principle governing api rate limiting algorithms?
2. What primary operational trade-off must be managed when configuring api rate limiting algorithms?
3. Which failure mode is most commonly observed when api rate limiting algorithms is misconfigured?

Decision scenario

You are designing a high-concurrency production system requiring reliable execution of api rate limiting algorithms under heavy traffic load.

Which architectural decision ensures maximum resilience, scalability, and system stability?

Primary sources