Design a Thread-Safe Multi-Rule Rate Limiter
SnowflakeSoftware Engineer · Technical ScreenLast updated
This problem tests the ability to design a thread-safe, flexible rate-limiting system that handles multiple constraints, atomic permit management, and graceful error handling.
Problem Statement
Design a thread-safe RateLimiter class that manages multiple independent rate-limiting rules. A rule is defined by a capacity C (max requests) and a time window W (in milliseconds). A request is only permitted if it satisfies all active rules.
Requirements
add_rule(capacity, window_ms): Dynamically add a new rate-limiting constraint.try_acquire(): Attempts to consume a permit across all rules. ReturnsTrueif successful,Falseotherwise.release(): If a request fails during processing (e.g., an exception), the permit must be returned to the bucket to maintain accurate counting.- Thread-Safety: The implementation must handle high concurrency without leaking permits or violating rate constraints.
Constraints
- The number of rules is small (1-10).
try_acquire()must be non-blocking.- Operations must be atomic across all rules: if a request cannot satisfy rule A but satisfies rule B, no permits should be consumed.
Example
limiter = RateLimiter()
limiter.add_rule(10, 1000) # 10 requests per second
if limiter.try_acquire():
try:
# Perform work
pass
except Exception:
limiter.release()
Edge Cases
- A
release()call triggered after a rule is removed. - Extremely high concurrency causing timestamp contention.
- Ensuring
try_acquireis atomic (all-or-nothing consumption).
Hints
Hint 1
Consider using a 'sliding window log' or 'token bucket' implementation for individual rules.
Hint 2
To ensure atomicity, use a reentrant lock or an atomic composite structure to update all rule states together.
Hint 3
For the 'release' functionality, keep track of which rule states were modified during a successful acquire to avoid over-counting if a request fails.
Follow-up questions
- How would you adapt this design to work in a distributed environment where multiple instances of the application share the same rate limits?
- If the rate-limited requests must be queued rather than dropped, what data structure would you use to manage fairness and prevent memory exhaustion?
- How would you ensure deterministic testing for this class given the dependency on system time?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.