Lesson 7 of 14
25. Rate Limiting

25.6 What do 429 and rate-limit headers look like?

3 min read+10 XP

At the club: A good bouncer doesn't just say "no". They say "full, come back in 6 seconds", and the sign by the door shows how many passes are left.

In the system: When a client is over its limit, return 429 Too Many Requests with a clear body, and tell the client when to retry:

HTTP/1.1 429 Too Many Requests Retry-After: 23 RateLimit-Limit: 100 RateLimit-Remaining: 0 RateLimit-Reset: 23 Content-Type: application/problem+json {"title": "Rate limit exceeded", "status": 429, "detail": "100 requests per minute on the free plan. Retry in 23 seconds."}
  • Retry-After (standard HTTP): seconds to wait, or a date.
  • Limit, remaining and reset headers on every response, not just the 429, so clients can slow down before hitting the wall. Many APIs use X-RateLimit-* names (GitHub sends x-ratelimit-limit, x-ratelimit-remaining and x-ratelimit-reset); an IETF draft standardises RateLimit header fields.
  • Document the limits per plan and endpoint. GitHub, for example, documents 5,000 requests an hour for authenticated users and 60 for unauthenticated ones.

Choices to make:

  • 429 vs 503: 429 means "you are sending too much"; 503 means "we are overloaded" (load shedding, Chapter 29).
  • Don't count rejected requests against the limit forever, or a misbehaving client never recovers; but do keep limits on 429 storms at the edge.
  • Clients should respect Retry-After and add jitter, or all rejected clients return at the same second (Chapter 21's herd).

Memory code: "Say 'too many', say how many are left, and say when to come back."