Expand description
Memory-bounded keyed rate limiter (LRU + idle eviction). Memory-bounded keyed rate limiter.
crate::bounded_limiter::BoundedKeyedLimiter wraps a map of per-key
governor::DefaultDirectRateLimiter instances behind a hard cap on the
number of tracked keys, with an idle-eviction policy and an LRU fallback
when the cap is reached.
§Why
The governor crate ships a governor::RateLimiter::keyed state store
whose memory grows monotonically with the number of distinct keys
observed. For server use cases keyed by source IP this is a
denial-of-service vector: an attacker spraying packets from spoofed or
distinct source addresses can exhaust process memory regardless of the
per-key quota.
crate::bounded_limiter::BoundedKeyedLimiter addresses this by:
- Holding a
std::collections::HashMapofK -> Entrywhere eachEntrycarries its own direct (per-key) limiter and alast_seentimestamp. - Capping the map at
max_tracked_keysentries. - On insert when the map is full, first pruning entries whose
last_seenis older thanidle_eviction, then – if still full – evicting the entry with the oldestlast_seen(“LRU eviction”). The new key is always inserted; honest new clients are never rejected because the table is full. - Updating
last_seenon every check (including rate-limit rejections) so an actively-firing attacker cannot dodge eviction by appearing idle. - Optionally spawning a best-effort background prune task. Cap enforcement does not depend on this task running – it is purely an optimization that reclaims memory between admission events.
§Trade-offs
- When a previously-evicted key reappears it gets a fresh quota.
This is documented behaviour: a key under sustained load keeps its
last_seenupdated and therefore is never evicted; eviction only targets idle keys. - The map uses
std::sync::Mutex(nottokio::sync::Mutex) since admission checks must be synchronous and never.await. - We do not log inside the critical section.
Structs§
- Bounded
Keyed Limiter - Memory-bounded keyed rate limiter.
Enums§
- Bounded
Limiter Error - Reason a
BoundedKeyedLimiter::check_keycall rejected a request.