rate-guard-core
A comprehensive rate limiting library for Rust applications with multiple thread-safe algorithms.
Features
- 5 Rate Limiting Algorithms: Token Bucket, Leaky Bucket, Fixed Window Counter, Sliding Window Counter, and Approximate Sliding Window
- Thread-Safe: All algorithms use non-blocking locks
- Zero Dependencies: Lightweight with no external dependencies
- Flexible Time: Works with any time unit via abstract “ticks”
- Configurable Tick Precision: Compile-time feature flags allow choosing
u64(default) oru128for tick units - Rust 1.60+: Compatible with older Rust versions
Quick Start
from crate.io
Add to your Cargo.toml:
[]
= { = "0.5.0" }
from Github
Add to your Cargo.toml:
[]
= { = "https://github.com/Kuanlin/rate-guard-core", = "v0.5.0" }
Tick Precision (u64 / u128)
By default, the crate uses u64 as the tick unit, allowing up to ~584 years of nanosecond-resolution time.
If your application needs ultra-long durations or ultra-high precision, you can enable u128 support via feature flags:
from crate.io
[]
= { = "0.5.0", = false, = ["tick_u128"] }
from Github
[]
= { = "https://github.com/Kuanlin/rate-guard-core", = "v0.5.0", = false, = ["tick_u128"] }
Usage Examples
Token Bucket
Perfect for APIs that allow occasional bursts while maintaining average rate:
use ;
let config = TokenBucketCoreConfig ;
// Option 1: Using `into()` – idiomatic Rust way to convert config into limiter
let limiter: TokenBucketCore = config.into;
// Option 2: Using `from()` – explicitly convert config into limiter
let limiter_alt = from;
Leaky Bucket
Great for maintaining steady traffic flow:
use ;
let config = LeakyBucketCoreConfig ;
// Option 1: Using `into()` – idiomatic Rust way to convert config into limiter
let limiter: LeakyBucketCore = config.into;
// Option 2: Using `from()` – explicitly convert config into limiter
let limiter_alt = from;
Fixed Window Counter
use ;
let config = FixedWindowCounterCoreConfig ;
// Option 1: Using `into()` – idiomatic Rust way to convert config into limiter
let limiter: FixedWindowCounterCore = config.into;
// Option 2: Using `from()` – explicitly convert config into limiter
let limiter_alt = from;
Sliding Window Counter
use ;
let config = SlidingWindowCounterCoreConfig ;
// Option 1: Using `into()` – idiomatic Rust way to convert config into limiter
let limiter: SlidingWindowCounterCore = config.into;
// Option 2: Using `from()` – explicitly convert config into limiter
let limiter_alt = from;
Approximate Sliding Window
A memory-optimized version of sliding window counter.
Formula:
Used = (1 - X%) * lastWindow + currentWindow where X is the proportion of request time within the current window.
use ;
let config = ApproximateSlidingWindowCoreConfig ;
// Option 1: Using `into()` – idiomatic Rust way to convert config into limiter
let limiter: ApproximateSlidingWindowCore = config.into;
// Option 2: Using `from()` – explicitly convert config into limiter
let limiter_alt = from;
Both
into()andfrom()are functionally equivalent in Rust.
into()is shorter and idiomatic;from()is more explicit and beginner-friendly.
These examples are duplicated to help both Rust newcomers and non-Rust readers understand the conversion logic.
Approximate Sliding Window
A memory-optimized version of sliding window counter.
Formula:
Used = (1 - X%) * lastWindow + currentWindow where X is the proportion of request time within the current window.
use ;
let config = ApproximateSlidingWindowCoreConfig ;
let limiter: ApproximateSlidingWindowCore = from;
Error Handling
All limiters' try_acquire_at returns SimpleRateLimitResult:
use ;
match limiter.try_acquire_at
Verbose Error Reporting
Each limiter also supports try_acquire_verbose_at(tick, tokens), which returns a VerboseRateLimitError with richer diagnostics:
ContentionFailure: Lock was unavailableExpiredTick { min_acceptable_tick }: Time went backwardsBeyondCapacity { acquiring, capacity }: Requested tokens exceed maxInsufficientCapacity { acquiring, available, retry_after_ticks }: Not enough tokens now, but suggests how long to wait before retrying
use ;
match limiter.try_acquire_verbose_at
try_acquire_verbose_atis useful for retry logic, logging, or adaptive throttling.
Time Management
The library uses abstract “ticks” for time. You can map any time source:
// Seconds
let tick = now.duration_since.unwrap.as_secs;
// Milliseconds
let tick = now.duration_since.unwrap.as_millis as u64;
// Custom time
let tick = my_monotonic_timer.elapsed_ticks;
Thread Safety
use Arc;
use thread;
use TokenBucketCore;
let limiter = new;
for _ in 0..10
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.