TweakCode
Worked Systems lessons

Rate Limiter · Stage 3 of 3

Distributed Counters with Atomic Increments

Enforce one limit across many servers with a shared atomic counter

Foundations

So far, each limit lived in one place. Now, what if the same caller's requests are spread across many server processes, so a count kept inside each process sees only its own share?

Keep the authoritative count in a shared store, under a key such as (caller, route, window), and update it with one atomic increment that returns the new value: allow if it is within the limit. Separate read and write steps would let two servers both pass the last allowed request. Give each key an expiry at the end of its window, and let each process keep a loose local prefilter that sheds obvious floods without granting anything.

Take a limit of 3 per minute and one caller's requests arriving on three different servers. Counted per server, each sees at most 2, so all 6 requests pass. Counted with one shared atomic increment, the fourth request reads 4 and is denied, whichever server handled it.

+1+1+1Server 1Server 2Server 3Shared countercount = 4 > 3
All three servers increment the same key atomically, so the count is the caller's true total. The fourth request sees 4 and is denied, whichever server it reached.
  • Caching

    The read path sits behind cache-aside.

    Open lesson

Case Scenario

The design brief

Limit the gateway

One edge gateway sits in front of many services. Some routes allow more traffic than others. Clients are untrusted.

Input
requests = [(0, "u", "read"), (10, "u", "read"), (20, "u", "read"), (30, "u", "read"), (31, "u", "export"), (32, "u", "export"), (65, "u", "read")], limits = {"read": 3, "export": 1}, window = 60
Output
[True, True, True, False, True, False, True]

To see how one shared counter enforces a limit across many servers, consider an edge gateway like Kong or Envoy in front of many services: routes allow different amounts of traffic, and clients are untrusted. Every gateway process atomically increments the same (user, route, minute) key, so read allows 3 per minute and export 1, however many processes run.

One edge gateway protects routes with different costs and runs as several processes. Per-process counts multiply every route’s quota, while one hot client can consume gateway CPU and shared-store bandwidth before the real check runs. The gateway must enforce read = 3 and export = 1 across all processes, while shedding an obvious local flood early.

Pro

The rest of this is on Pro

The idea above is free. The walkthrough, the cost, and the practice are on Pro.