What happened?
Both built-in per-client rate-limiting middleware classes keep limiter objects in an in-memory dictionary keyed by the configured client ID. Entries for inactive clients are never reclaimed. In the sliding-window limiter, expired timestamps are pruned only when that same client makes another request, so inactive clients remain retained as well.
A deployment that derives IDs from high-cardinality or user-controlled values can accumulate limiter state for every identity seen during the process lifetime. A local reproduction sent requests under 2,000 synthetic client IDs; both middleware instances retained 2,000 limiter entries. This is a memory-retention issue, not a rate-limit bypass.
Could idle limiter entries be removed once their state can no longer affect future rate-limit decisions, while keeping active requests safe?
Example Code
Version Information
- FastMCP main: `5baeacfe20eca735cb949564b4915f93a622b916`
- Python: 3.12.15
- OS: macOS 15.0.1 arm64
What happened?
Both built-in per-client rate-limiting middleware classes keep limiter objects in an in-memory dictionary keyed by the configured client ID. Entries for inactive clients are never reclaimed. In the sliding-window limiter, expired timestamps are pruned only when that same client makes another request, so inactive clients remain retained as well.
A deployment that derives IDs from high-cardinality or user-controlled values can accumulate limiter state for every identity seen during the process lifetime. A local reproduction sent requests under 2,000 synthetic client IDs; both middleware instances retained 2,000 limiter entries. This is a memory-retention issue, not a rate-limit bypass.
Could idle limiter entries be removed once their state can no longer affect future rate-limit decisions, while keeping active requests safe?
Example Code
Version Information