System designLoading progress…

Rate limits

Place authentication, object authorization and resource limits at explicit application boundaries.

Rate limits

A token bucket (capacity C, refill r per second) allows bursts up to C and a steady rate r: with C = 10 and r = 2, an 8-token request leaves 2, two seconds later there are 6, a 7-token request is denied (and leaves 6) and a 6-token request is accepted. A fixed window resets on a boundary, so 100 requests at 0:59 plus 100 at 1:00 all pass; a sliding window does not. Several instances need a shared counter or an accepted approximation.

t=0s cost 8: accepted → 2 tokens left t=2s cost 7: DENIED → 6 tokens left t=2s cost 6: accepted → 0 tokens left a denied request does not take or create tokens

Different algorithms give different burst contracts. A limit shared by several instances needs coordination (a shared counter) and a policy for when that store is unavailable; independent per-instance counters can both over- and under-enforce.

Compare the two contracts.

Predict first. Can independent per-instance counters enforce one exact global limit without coordination?

Chapter context

A distributed application must identify callers and control which resources and effects they may access. Tenant boundaries and resource budgets must be enforced by trusted components rather than inferred from client-supplied identifiers.

Chapter reference: math, worked example & code

This section belongs to the whole chapter, so it is the same on every lesson in it and may cover a different lesson's topic. The code for the experiment you just ran is inside the experiment itself.

Math and notation

For a token bucket with capacity C, refill rate r, previous tokens b and elapsed time dt:

b′=min⁡(C,b+r dt).b'=\min(C,b+r\,dt).

Accept cost k only when b′≥kb'\ge k, then subtract k atomically. Clock behavior, concurrency and shared enforcement are additional implementation requirements.

Worked example

A bucket holds at most 10 tokens and refills 2/s. An 8-token request at time zero leaves 2. Two seconds later it has 6. A request costing 7 is denied and leaves 6; a request costing 6 is accepted and leaves zero. Rejected operations should not accidentally create negative credit under this contract.

Reference code

The following example uses the Python standard library and does not call a remote service.

capacity,rate,tokens=10,2,10
tokens-=8
assert tokens == 2
tokens=min(capacity,tokens+rate*2)
assert tokens == 6
assert tokens < 7
assert tokens >= 6
tokens-=6
assert tokens == 0

Python examples are provided for study and local execution; this page does not execute Python.

Common mistakes

Authentication is not object-level authorization. Cache and worker paths can cross tenant boundaries too. A global rate limit requires a stated distributed enforcement contract.