Architecture & System Design › System Design Fundamentals
Designing a Rate Limiter
Counting requests across many servers under high load.
Also known as: rate limiter design, distributed rate limiting, design rate limiter
Designing a rate limiter enforces “at most N requests per window” across distributed servers: counter per key (user, IP, API key) in a shared store, checked on every request, rejecting over-limit with 429 plus retry guidance. The exercise is distributed counting at request speed — correct enough, fast enough, and kind to clients.
request → identify key → shared counter (sliding window) → allow / 429+Retry-After
Key decisions: algorithm (token bucket for burst-plus-average, sliding window for strict smoothing — see rate-limiting algorithms), store (in-memory per node is cheap but N× lenient; shared Redis/Cassandra is exact but adds a hop), key granularity (per-user beats per-IP for fairness), and failure mode (fail open on limiter outage? or closed?).
The classic mistakes:
- Per-node counting. Ten servers × 100/min each = 1000/min real limit. Either share the counter or accept and document the multiplier.
- Counter hot keys. One viral user hammering a single counter serialises on it; shard counters or accept approximate counting at extremes.
- No headers. Clients can’t back off gracefully without limit/remaining/reset feedback. Standard headers plus
429plusRetry-After. - Limiter latency on the hot path. A cross-region counter read per request adds real milliseconds; co-locate counters, batch, or use local-with-sync approximations.
- Fail-closed by default. A limiter outage 500-ing all traffic turns protection into the outage. Decide fail-open vs closed per endpoint criticality.
- One limit for all. Login attempts, API reads and bulk imports need different keys, windows and consequences. Tier limits by abuse potential and cost.
- Punishing shared IPs. Per-IP limits behind carrier NAT throttle thousands innocently. Key on identity where possible; layer IP limits loosely.
Why it teaches: distributed counters, approximation trade-offs, failure-mode design and client cooperation — rate limiting is coordination theory meeting production reality. Count shared, communicate clearly, fail thoughtfully.