Book a 30-min callBook a call

Designing a rate limiter: token bucket, sliding window and limits across many servers

How fixed window, sliding window and token bucket rate limiters work, how to hold one limit across many servers, and how to answer with 429 and Retry-After.

A bucket of token circles with a refill arrow above it, three request blocks passing, and two more held back by a stop sign.
Written by
BYD Tech
Published
Topic
Deep dives
Reading time
16 min read

Questions people ask

What is the difference between a token bucket and a leaky bucket?

A token bucket allows a burst up to its capacity and then holds the refill rate. A leaky bucket in its queue form accepts a burst into a queue and releases requests at a fixed rate, so it smooths traffic by adding delay. Used as a meter that rejects instead of queueing, a leaky bucket behaves like a token bucket with the same rate and size.

Should a rate limiter fail open or fail closed when its store is down?

It depends on what the limit protects. For ordinary user traffic, most teams fail open, often with a conservative local limiter on each node as a fallback. For limits that stop abuse, such as login attempts, or that protect a fragile backend, failing closed is safer. Decide it in advance and test it.

Should I return 429 or 503 when a client is over its limit?

Return 429 Too Many Requests, defined in RFC 6585, when one client has sent too many requests, ideally with Retry-After. Keep 503 Service Unavailable for when the whole service is overloaded or down. Some proxies default to 503 for rate limiting, so check the setting.

How do I rate limit by IP address behind a load balancer?

Read the client address from the forwarding header that your own proxy or load balancer sets, using the entry it appended rather than the leftmost one, which the client controls. Expect many users behind one address on office and mobile networks, and limit IPv6 clients by prefix rather than by single address.

Are the RateLimit header fields an official standard?

Not yet. As of November 2026 they are defined in draft-ietf-httpapi-ratelimit-headers, version 11, an Internet-Draft of the IETF HTTPAPI working group. Details can still change before it becomes an RFC, and many APIs still send the older X-RateLimit headers.

Building something like this?