Beyond Code & Karma · System Design
Four algorithms decide whether each request gets a 200 or a 429. Channel the flood into a steady stream — explained, compared, and visualized live.
Chapter 01 — The Foundation
Rate limiting caps how many requests a client may make in a given time, so one caller can't exhaust your capacity, run up your bill, or brute-force a login. Over the limit, the server replies 429 Too Many Requests instead of doing the work. The interesting part is how you count — four algorithms accept and reject the same traffic differently.
The Cosmic Connection
In the Yoga Sutras, Sanyama is mastery through restraint — measured action that channels raw force toward a purpose instead of letting it run wild. A rate limiter is karma yoga in code: a sacred river channeled so it nourishes the fields instead of flooding them.
"Measured action channels a flood into a steady stream, so the system endures instead of drowning."
Chapter 02 — Show Me The Code
The default limiter, and the cleanest to read. Refill lazily on each check — no background timer needed.
// Token bucket — the default for most public APIs class TokenBucket { constructor(capacity, refillPerSec) { this.cap = capacity; this.rate = refillPerSec; this.tokens = capacity; this.last = now(); } allow() { const t = now(); // refill based on elapsed time, capped at capacity this.tokens = Math.min(this.cap, this.tokens + (t - this.last) * this.rate); this.last = t; if (this.tokens >= 1) { this.tokens -= 1; return true; } // → 200 return false; // → 429 } }
allow(), add
(elapsed × rate) tokens, capped at capacity. State is one
number and a timestamp — trivial to store per-user in Redis.
Token available? Spend it → 200. None left → 429. Bursts allowed up to the saved token count.
Room in the queue? Enqueue → 200. Full → overflow → 429. The queue drains at a constant rate.
Counter below limit this window? Increment → 200. At limit → 429. Resets to zero at the boundary.
Fewer than limit timestamps in the last window seconds? Record → 200. Otherwise → 429. Old stamps age out.
Chapter 03 — Live Visualization
A token bucket, capacity 10, refilling 2/sec. Send single requests or burst — watch tokens drain faster than they refill and the 429s start.
Chapter 04 — Deep Dive
Where the basics stop and the production reality begins.
Both hold capacity N, but token bucket limits the average rate and tolerates bursts (saved tokens spend all at once), while leaky bucket limits the output rate and smooths everything (a queue draining at a fixed rate). Token bucket favors throughput; leaky bucket favors a steady, predictable downstream load. Rule of thumb: public API → token; feeding a fragile worker → leaky.
Fixed window keeps one counter per window (say 10 per 5s) and resets at the boundary. Burst right before the reset and again right after, and you push nearly double the limit in a short span — each window counts independently. In the visualizer, switch to Fixed Window and try it.
Global limits are rare. Key the limiter by identity — user ID for authenticated requests, API key for machines, client IP as the anonymous fallback. Store each key's state in a shared fast store (Redis) with a TTL so idle keys expire, so the limit holds across every server instance. In practice you layer them: a generous per-IP limit to blunt abuse plus a tighter per-user limit for fairness.
A well-behaved API doesn't just slam the door. Return
429 Too Many Requests with a Retry-After
header (seconds to wait) and the RateLimit-Limit /
RateLimit-Remaining / RateLimit-Reset
headers so clients can self-throttle instead of hammering you.
Clients should back off exponentially, not retry immediately.
Chapter 05 — Quick Reference
| Algorithm | Bounds | Bursts? | Cost | Best for |
|---|---|---|---|---|
| Token Bucket | Average rate | Yes (up to bucket) | Cheap | Public / REST APIs |
| Leaky Bucket | Output rate | No | Cheap | Feeding fragile downstream |
| Fixed Window | Count / window | ~2× at boundary | Cheapest | Coarse limits, one Redis counter |
| Sliding Window | Count / rolling | No boundary game | More memory | Login / OTP throttling |
Chapter 06 — Dharma & The Limit
A refusal is not always denial — sometimes it is protection. The 429 is dharma's gate: it says "not now" so the system can keep its promise to everyone else. To rate-limit is to practise aparigraha — non-grasping — refusing to let one caller consume what belongs to the whole.
The token bucket is saved merit, spent one measured action at a time. The leaky bucket is a flood made gentle. Neither hoards, neither floods — each holds the middle path between starving the system and drowning it. That balance is the discipline.
"Channel the river; do not dam it, do not let it flood." — Sanyama, interpreted for backend engineers 🙏
Chapter 07 — Test Yourself
Three questions. No cheating. Your karma is watching.
The Enlightenment
कर्म करो, फल की चिंता मत करो