Adding Custom Algorithms
Relevant source files
The following files were used as context for generating this wiki page:
FastLimit is designed with an extensible architecture that allows developers to implement and integrate new rate-limiting algorithms. The system relies on a consistent interface defined by base classes and a Redis-backed execution model to ensure high performance and atomicity across distributed environments.
Adding a custom algorithm involves extending the core RateLimitAlgorithm interface, implementing the required check and reset logic, and optionally providing Lua scripts for atomic backend operations. This ensures that new algorithms can take advantage of the existing infrastructure for metrics, multi-tenancy, and cost-based limiting.
Sources: fastlimit/limiter.py, README.md:120-130
Core Architecture for Algorithms
The algorithm architecture in FastLimit follows a provider pattern where the RateLimiter class acts as the orchestrator, routing requests to specific algorithm implementations based on configuration or decorator parameters.
The Algorithm Interface
All algorithms must inherit from the RateLimitAlgorithm abstract base class. This base class defines the contract for how the RateLimiter interacts with the specific logic of the algorithm.
The diagram shows the inheritance structure where specific algorithms implement the abstract methods of the base class.
Sources: fastlimit/algorithms/base.py, fastlimit/algorithms/sliding_window.py:18-30
Implementation Steps
1. Define the Algorithm Logic
A new algorithm must be implemented within the fastlimit/algorithms/ directory. The implementation requires overriding three primary methods:
| Method | Purpose |
|---|---|
check() | Executes the core rate limiting logic. It typically calls a Lua script via the backend to ensure atomicity. |
reset() | Clears the rate limit data (Redis keys) associated with a specific identifier. |
get_usage() | Returns current consumption statistics, such as remaining tokens or current window counts. |
Sources: fastlimit/algorithms/sliding_window.py:85-115, fastlimit/limiter.py:270-300
2. Integrate with the Redis Backend
For high-performance and race-condition-free operations, algorithms should utilize Redis Lua scripts. The RedisBackend class (referenced in the RateLimiter) handles the execution of these scripts. When adding a custom algorithm, a corresponding .lua script should be placed in fastlimit/scripts/.
The flow illustrates how the RateLimiter delegates the actual check to the algorithm implementation, which then interacts with Redis.
Sources: fastlimit/limiter.py:186-220, CONTRIBUTING.md:130-150
3. Registering the Algorithm
The RateLimiter must be made aware of the new algorithm. Currently, this involves updating the internal routing logic within fastlimit/limiter.py. The check_with_info method contains the logic that selects which backend method to call.
# Example routing in fastlimit/limiter.py
if algorithm == "fixed_window":
result = await self.backend.check_fixed_window(...)
elif algorithm == "token_bucket":
result = await self.backend.check_token_bucket(...)
elif algorithm == "sliding_window":
result = await self.backend.check_sliding_window(...)
Sources: fastlimit/limiter.py:188-216
Handling Data Precision
FastLimit uses integer-only arithmetic with a 1000x multiplier to maintain precision without floating-point issues in Redis Lua scripts. Custom algorithms should adhere to this convention:
max_requestsis multiplied by 1000.costdefaults to 1000 (representing 1 unit).- Results from the backend (like
remaining) should be divided by 1000 before being returned to the user.
Sources: fastlimit/limiter.py:179-182, fastlimit/algorithms/sliding_window.py:165-175
Testing Custom Algorithms
The project follows a strict testing guideline for new features. Custom algorithms should include:
- Unit Tests: In
tests/test_algorithms.pyto test the Python logic. - Integration Tests: Validating the Lua script behavior against a real Redis instance.
- Concurrency Tests: Ensuring no race conditions occur under heavy load.
Sources: CONTRIBUTING.md:200-240, README.md:278-290
Conclusion
Adding a custom algorithm to FastLimit requires implementing the RateLimitAlgorithm interface and ensuring atomic state transitions via Redis. By following the project's established pattern of integer-based precision and Lua-backed logic, developers can create robust, production-ready throttlers tailored to specific application needs.