Skip to main content

Crate rate_net

Crate rate_net 

Source
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 check on 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 loom and proptest.
  • 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

FeatureDefaultDescription
stdyesStandard 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.
algorithmsnoThe full algorithm suite beyond the default token bucket: leaky bucket, fixed window, sliding-window log, sliding-window counter.
asyncnoOptional async-friendly wrapper layer. Additive only — the core has no runtime dependency.

Structs§

AsyncLimiter
An async-friendly wrapper around a RateLimiter.
Builder
A fluent builder for a RateLimiter when 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: limit requests per period, per key, with a burst ceiling.
RateLimiter
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.
RateLimiterError
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.toml at compile time.

Traits§

Limiter
The shared rate-limiting surface, independent of the algorithm behind it.