Problem statement
Design the object model and core APIs for an in-process rate limiter library that a service embeds to throttle traffic per caller. The limiter answers one question per request — allow this call now, or deny it — and it must do so under a chosen counting policy (token bucket, leaky bucket, or a sliding window) that the embedder picks at wiring time. Whatever sits on top (a request filter, an RPC interceptor, a test) merely asks the limiter and reacts to the verdict.
Operating context. One process, many concurrent worker threads sharing a single limiter instance. Callers are identified by an opaque key (a user id, an API key, an IP, or a route name); the limiter keeps an independent counter per key and lazily creates one the first time a key is seen. Each key is governed by a limit spec (for example, a sustained rate plus a burst allowance) resolved from configuration. Because the algorithm is time-driven, the limiter must read "now" from an injected clock rather than a global system call, so a test can advance time deterministically and prove refill and expiry behavior. Threads call the allow/deny API concurrently on the same key, so per-key state must stay correct without a single global lock that serializes unrelated keys.
Out of scope. Distributed or cross-process coordination and any shared network store, the transport or framework that invokes the limiter, persistence of counters across restarts, dynamic hot-reload of the config source, and the 429/Retry-After wire encoding. Model the in-process object graph and its concurrency, not the service around it.
What to produce. The class hierarchy (the limiter facade, the per-key limiter/state, the pluggable algorithm abstraction and at least two concretes, a clock abstraction, and value objects such as a limit spec and a decision), the public API each type exposes, and the state transitions of a single key's counter (idle to active to reclaimed) and of a decision (allowed, denied with a retry hint). Be explicit about: how a new algorithm is added without editing the facade, how counters are isolated and reclaimed per key, how concurrent updates to one key stay atomic without a global lock, and how the injected clock makes refill and window-roll testable to the tick.
Requirements
This assessment is a Premium feature.
The statement above is free to read. The functional and non-functional requirements, and the graded canvas that scores your design against them, come with Premium.
Topics
- System Design LLD
- Patterns Strategy
- Concurrency Locks
- Oop Solid
- Testability Clock