A single per-tool limit is a cap on the tool, not on any caller. If a tool allows 600 calls per minute and one tenant sends 590 of them, the remaining tenants share 10 calls. The limit held, the tool stayed up, and the small caller still got starved. This is the noisy-neighbor problem in its plainest form: a limit that constrains the aggregate says nothing about how the aggregate is divided.
The usual first fix is to partition the tool into separate pools, one per tenant. That works, but it creates a new problem: each pool sits idle when its tenant is quiet, and the tool's real capacity goes unused while another tenant is throttled against a hard partition. Token bucket as a mechanism is a bandwidth cap by design; the classic networking treatment notes that a token bucket does not redistribute an idle sender's allocation to other senders, unlike fair queuing token bucket rate limiting. So you get fairness between tenants at the cost of unused capacity.
Fixed windows add a second failure. A caller can send its full allowance at the end of one window and again at the start of the next, double the intended throughput across the boundary rate limiting algorithms. With per-caller windows stacked under a per-tool window, boundary bursts from many callers land at once against the shared tool cap.
The design goal is therefore: guarantee every caller a minimum, let heavy callers use spare capacity in proportion to their weight, and never let a floor be violated to fund someone else's burst. That is a weighted allocation with a floor and a borrowing rule, enforced by per-caller buckets.



