Functional
- Apply per-tenant, per-user, or per-route policies.
- Support sustained rate plus controlled burst capacity.
- Return remaining budget and retry guidance.
Enforce fair request budgets across many stateless service instances.
A network call for every request is expensive and risky.
Counters need expiry and memory-efficient representation.
Policies can be versioned and cached aggressively.
Use local tokens or regional batching on critical paths.
These are reference assumptions, not universal facts. In an interview or architecture review, change them when the product context changes.
/v1/checkEvaluate principal, resource, and cost; return allow plus retry_after./v1/policies/{id}Publish a versioned rate policy./v1/usage/{principal}Inspect approximate current budget for operations.policy_id, matcher, rate, burst, action, versionImmutable versions allow atomic rollout and rollback.principal+policy PK, tokens, last_refill_at, expires_atUpdate atomically with server-side time.Own limits and rollout rules
Make the hot-path decision
Coordinate shared usage windows
Protect dependencies during store failure
Token bucket fits bursty APIs; sliding-window counters give intuitive quotas but cost more state. Use fixed windows only where boundary bursts are acceptable.
Lease token batches from a regional store to each gateway. The hot path spends local tokens; unused leases expire. Overshoot is bounded by lease size × active gateways.
Authentication, payment, and write-amplifying endpoints may fail closed; ordinary reads often fail open with a conservative local cap. Encode this choice in policy so incident behavior is predictable.
Fail open or closed by endpoint risk; never use one global default.
Partition by tenant and isolate heavy hitters before they saturate shared shards.
Move here when: Single replica or best-effort limits.
Move here when: Multiple replicas need coordinated fairness.
Move here when: Limiter latency or store QPS dominates.
Strong answer signal: Derive the bound from lease size and concurrent holders.
Strong answer signal: Use authoritative monotonic/server-side elapsed time, not client wall clocks.
Strong answer signal: Versioned push, jittered refresh, and last-known-good fallback.