Skip to content
API Design Learn/Production REST I: Performance & Reliability
Browsing as a guest. Sign in to save your progress and earn XP as you complete chapters.

Rate Limiting

7 min read

You'll learn to

  • -Communicate rate limit state to clients via standard headers, so well-behaved clients can self-throttle before being rejected
  • -Choose the right HTTP response (429, with Retry-After) and explain why silent throttling is worse than an explicit signal

Rate limiting protects a service from being overwhelmed by any single client - but the API-design half of this problem (distinct from the algorithm covered in LLD Fundamentals' rate limiter chapter) is how the limit gets communicated to callers, since an API that rejects requests without explanation forces every client to guess at the limit through trial and error.

Conventional Rate Limit Headers

These `X-RateLimit-*` headers are a widely-adopted convention (GitHub, Twitter, Stripe all use this shape), not a ratified HTTP standard - there is a newer official `RateLimit` header field (RFC-track, no `X-` prefix), but the `X-RateLimit-*` form below remains what you will see in practice at most companies and is safe to use in an interview if you name it as convention rather than spec.

Telling the client exactly where it stands before it gets rejected
GET /orders
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 37
X-RateLimit-Reset: 1735689600
  • -`X-RateLimit-Limit`: the total requests allowed in the current window.
  • -`X-RateLimit-Remaining`: how many requests are left before the client gets throttled.
  • -`X-RateLimit-Reset`: when the window resets (a Unix timestamp), so the client knows exactly how long to back off.

Including these headers on every response - not just the one that finally gets rejected - lets a well-implemented client self-throttle proactively, slowing down as `Remaining` approaches zero rather than firing requests at full speed until it hits a wall.

429 Too Many Requests, With Retry-After

An explicit rejection with a concrete retry time
GET /orders
HTTP/1.1 429 Too Many Requests
Retry-After: 42
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1735689600

{"error": "Rate limit exceeded. Retry after 42 seconds."}

`Retry-After` (in seconds, or an HTTP date) tells the client exactly how long to wait, which is strictly better than a client guessing at a backoff interval - too short a guess means hammering the limit again immediately, too long wastes time the server would have accepted the request.

Silently dropping requests once a limit is hit (returning nothing, or a generic timeout) is worse than an explicit 429 - it leaves the client unable to distinguish "I'm being rate limited" from "the server is actually down," which leads to the wrong recovery behavior in either case.

Interview Signal is part of Pro

See a real weak answer next to a real strong one for this exact topic.

Quiz is part of Pro

Test what you just read with a short quiz, and bank the XP.

Ready to Build This?

Design Rate Limit Fortress in the API Design Lab's Production Patterns act.

ScaleDojo Logo
Initializing ScaleDojo