Rater
A high-performance, lock-free rate limiting library for Rust. It uses the token bucket algorithm under the hood and comes with built-in per-IP rate limiting, so you can drop it into a web server and start throttling requests in minutes.
Features
- Lock-free & thread-safe -- atomic CAS operations instead of mutexes, so threads never block each other
- Fast -- cache-aligned structures, platform-specific hints (PAUSE on x86, YIELD on ARM), ~29 ns per
try_acquirecall - Adaptive refill -- automatically adjusts refill rate when your system is under sustained pressure
- Per-IP rate limiting -- built-in
IpRateLimiterManagerwith automatic cleanup of idle clients - Real-time metrics -- success rates, pressure detection, health status -- all available at a glance
- Lightweight -- just three dependencies: dashmap, ahash, and tracing
- Safe Rust --
unsafeis used only for platform-specific CPU pause instructions
Installation
Add rater to your Cargo.toml:
[]
= "0.1.2"
If you also want serde serialization support:
[]
= { = "0.1.2", = ["full"] }
Quick Start
Basic Rate Limiting
use RateLimiter;
Per-IP Rate Limiting
Perfect for web servers -- each client IP gets its own token bucket:
use ;
use IpAddr;
use Arc;
Builder Pattern
For full control over every knob:
use ;
Advanced Configuration
Rate Limiting Strategies
use ;
// 100 requests per second (with 2x burst capacity by default)
let config = per_second;
// 1,000 requests per minute
let config = per_minute;
// Full manual control: 500 max tokens, refill 50 tokens every 1000 ms
let config = new
.with_burst_multiplier // allow bursts up to 3x the refill rate
.with_ordering; // strongest memory ordering
Monitoring and Metrics
use RateLimiter;
let limiter = new;
for _ in 0..50
let metrics = limiter.metrics;
println!;
println!;
println!;
println!;
Custom Cleanup Settings
Control how aggressively idle IP entries are pruned:
use ;
use Arc;
let config = per_second;
let manager = new;
let = manager.clone.start_stoppable_cleanup_thread;
// ... use the manager ...
// Shut down gracefully
stop_tx.send.unwrap;
handle.join.unwrap;
Performance
Rater is built for high-concurrency scenarios. Here are some highlights from the benchmark suite (Apple M-series, cargo bench):
| Operation | Latency | Throughput |
|---|---|---|
try_acquire() (single thread) |
~29 ns | ~35 M ops/s |
try_acquire_n(50) (single thread) |
~30 ns | ~1.67 G tokens/s |
get_limiter() (IP lookup) |
~10 ns | — |
try_acquire() per IP |
~38 ns | — |
| Concurrent acquire (2 threads) | ~90 µs / 2k ops | ~22 M ops/s |
| Concurrent acquire (8 threads) | ~1.2 ms / 8k ops | ~6.4 M ops/s |
| IP manager (8 threads) | ~122 µs / 8k ops | — |
| Metrics snapshot | ~2.3 ns | — |
Design choices that make this fast:
- Lock-free CAS loops with bounded retries (no infinite spinning)
- Cache-aligned structs to prevent false sharing across cores
- Platform-specific spin hints (x86 PAUSE / ARM YIELD)
- Adaptive refill that backs off under sustained pressure
Run the benchmarks yourself:
Architecture
Core Components
-
RateLimiter-- the lock-free token bucket- Atomic token counter (u64 on 64-bit, u32 on 32-bit)
- Time-based auto-refill with adaptive backoff
- Backpressure detection
-
IpRateLimiterManager-- per-IP rate limiting- Sharded concurrent hash map (DashMap) for IP tracking
- Automatic + emergency cleanup when approaching capacity (10k IPs max)
- LRU-like eviction of idle entries
-
Metrics -- real-time health monitoring
- Success / rejection rates and counts
- Pressure ratio and consecutive-rejection streaks
- Health status enum (
Healthy,Warning,Critical)
Memory Ordering
Pick the trade-off that fits your use case:
| Ordering | When to use |
|---|---|
Relaxed |
Maximum speed, approximate counts are fine |
AcquireRelease |
(default) Good balance of speed and correctness |
Sequential |
Strict ordering required (debugging, auditing) |
Use Cases
- API gateways -- throttle requests per client IP
- Microservices -- backpressure and circuit-breaker patterns
- Game servers -- prevent spam and abuse
- IoT gateways -- control device message rates
- Background workers -- throttle calls to external APIs
Examples
The examples/ directory has runnable demos:
basic.rs-- simple rate limitingip_limiting.rs-- per-IP rate limiting with monitoring
Testing
Contributing
Contributions are welcome! Feel free to open an issue or submit a PR.
- Fork the repo
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
Licensed under either of:
at your option. See LICENSE for details.
Made with care by Khaled