Nice walkthrough. Two things worth adding for anyone taking this to production: (1) fixed-window counters have a boundary stampede problem — a burst at the end of one window plus a burst at the start of the next can double the intended rate. Sliding-window log or token bucket fixes it. (2) The in-memory approach breaks the moment you run more than one replica — each instance gets its own budget. The standard production answer is a Redis-backed token bucket (a small Lua script keeps the check-and-decrement atomic). Happy to sketch it if useful.