Expand description
§rate-net
A powerful, lock-free rate limiter for Rust. It answers one question as fast
as the hardware allows — “is this key allowed right now?” — and answers it
with a Decision (allow / deny plus a retry-after), across multiple
algorithms, while tracking per-key state under high contention. Per-key
state lives in a sharded concurrent map, so unrelated keys never contend and
throughput scales with core count; each key’s bucket is lock-free and memory
is bounded by eviction, so a flood of unique keys hits a cap instead of
growing without limit.
rate-net does not reimplement token-bucket accounting. It consumes
better-bucket for that and reads
time from clock-lib, then adds the
per-key, multi-algorithm, retry-after machinery around them. It is the
anchor crate of the -net domain group and is consumed by gatekeepers (such
as bouncer-io) through the clean decision API — they call check and never
reach into its internal state.
§Status
Stable (1.0.0). The public API is frozen until 2.0. The five
algorithms sit behind the one Limiter trait (token bucket by default; the
leaky bucket and window algorithms under the algorithms feature), with the
Tier-2 Builder, an optional AsyncLimiter await-until-ready layer
(async feature), runnable
examples, and a
criterion suite. Per-key state lives in a purpose-built sharded store
(an existing-key check takes only a shard read lock
plus the algorithm’s atomic accounting, so unrelated keys never contend),
memory is bounded by eviction, and the steady-state check is
allocation-free. Every public type is Send + Sync + 'static, asserted
at compile time. The safety invariants — never over-admit, bounded memory —
are proved by proptest (per algorithm), loom, a multi-threaded stress
suite across every algorithm, an allocation audit, and an adversarial-traffic
suite, and the surface is validated through a representative gatekeeper
consumer.
use rate_net::{RateLimiter, Decision};
// 100 requests per second, per key.
let limiter = RateLimiter::per_second(100);
match limiter.check("user:42") {
Decision::Allow => {
// allowed — serve the request
}
Decision::Deny { retry_after } => {
// denied — return 429 with `Retry-After: retry_after`
let _ = retry_after;
}
_ => {}
}§Design goals
- Lock-free per key. Each key’s bucket delegates to
better-bucket’s atomic compare-and-swap core; no lock sits on the check path. - Sharded state. Per-key state lives in a sharded concurrent map, so unrelated keys land in different shards and never serialize on each other. Throughput scales with cores; shard count is tunable.
- Zero-allocation steady state. A
checkon an existing key allocates nothing; allocation happens only the first time a key is seen. - Bounded memory. Idle keys are evicted (LRU/TTL) on an amortized, incremental schedule that never stops the world on the hot path. A hostile unique-key flood reaches the eviction cap and stays there.
- Never over-admits. For any key and window, admitted requests never
exceed the configured quota under any concurrent interleaving — proven per
algorithm with
loomandproptest. - Lazy, runtime-free. Refill and expiry are computed from a monotonic clock on access; there is no background timer thread and the core has no async-runtime dependency.
§Feature flags
| Feature | Default | Description |
|---|---|---|
std | yes | Standard library. Required for the sharded per-key store and eviction. With it off the crate is no_std; the scaffold then exposes only VERSION, and the pared-down single-key mode follows in a later release. |
algorithms | no | The full algorithm suite beyond the default token bucket: leaky bucket, fixed window, sliding-window log, sliding-window counter. |
async | no | Optional async-friendly wrapper layer. Additive only — the core has no runtime dependency. |
Structs§
- Async
Limiter - An async-friendly wrapper around a
RateLimiter. - Builder
- A fluent builder for a
RateLimiterwhen the Tier-1 constructors are not enough. - Eviction
- How the limiter bounds the memory its per-key state can occupy.
- Key
- An opaque identity a rate limit is tracked against.
- Quota
- A rate limit:
limitrequests perperiod, per key, with aburstceiling. - Rate
Limiter - A keyed rate limiter.
Enums§
- Algorithm
- Selects the algorithm a limiter uses to decide a request.
- Decision
- The result of checking a key against its limit.
- Rate
Limiter Error - A limit configuration rejected at construction time.
Constants§
- DEFAULT_
MAX_ KEYS - The default key-capacity cap, applied unless overridden.
- VERSION
- The version of this crate, taken from
Cargo.tomlat compile time.
Traits§
- Limiter
- The shared rate-limiting surface, independent of the algorithm behind it.