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
Pre-1.0 beta (0.9.0): the API is frozen (since 0.7.0) and locked
in at the type level too — every public type is Send + Sync + 'static
and that is asserted at compile time. The integration shake-out at 0.8.0
confirmed the surface is consumable through the public allow/deny API only,
and 0.9.0 widens the concurrency coverage: a single hot key under eight
threads against every algorithm admits exactly its quota — never more
(no over-admit, no torn updates) and never fewer (no lost decrements, no
deadlock). 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. From here, the only changes before 1.0 are bug fixes
and documentation polish.
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.