Getting Started

Quickstart (Local)

[object Object]

Use the local provider when all rate limiting happens inside one process and you want the lowest possible overhead.

Create a limiter with defaults

RateLimiter::builder().build() is the shortest path. It also starts background cleanup automatically.

use trypema::{RateLimit, RateLimitDecision, RateLimiter};

let rl = RateLimiter::builder().build().unwrap();
let rate = RateLimit::try_from(5.0).unwrap();

assert!(matches!(
    rl.local().absolute().inc("user_123", &rate, 1),
    RateLimitDecision::Allowed
));

Create a limiter with explicit options

Use RateLimiter::new(...) when you want full control. In this path, you start cleanup yourself.

use std::sync::Arc;

use trypema::{
    HardLimitFactor, RateGroupSizeMs, RateLimit, RateLimiter, RateLimiterOptions,
    SuppressionFactorCacheMs, WindowSizeSeconds,
};
use trypema::local::LocalRateLimiterOptions;

let rl = Arc::new(RateLimiter::new(RateLimiterOptions {
    local: LocalRateLimiterOptions {
        window_size_seconds: WindowSizeSeconds::new_or_panic(60),
        rate_group_size_ms: RateGroupSizeMs::new_or_panic(10),
        hard_limit_factor: HardLimitFactor::new_or_panic(1.5),
        suppression_factor_cache_ms: SuppressionFactorCacheMs::default(),
    },
}));

rl.run_cleanup_loop();

let _rate = RateLimit::try_from(5.0).unwrap();

Read before you write

For the local absolute strategy, is_allowed(...) is the clearest way to inspect the current state without recording a request.

use trypema::{RateLimit, RateLimitDecision, RateLimiter};

let rl = RateLimiter::builder().build().unwrap();
let rate = RateLimit::try_from(5.0).unwrap();

assert!(matches!(
    rl.local().absolute().is_allowed("user_123"),
    RateLimitDecision::Allowed
));

assert!(matches!(
    rl.local().absolute().inc("user_123", &rate, 1),
    RateLimitDecision::Allowed
));

Inspect suppression state

get_suppression_factor(...) tells you how much shedding pressure is currently active for a key.

use trypema::{RateLimiter, RateLimit};

let rl = RateLimiter::builder().build().unwrap();
let rate = RateLimit::try_from(5.0).unwrap();

let limiter = rl.local().suppressed();
let _ = limiter.inc("user_123", &rate, 1);

assert_eq!(limiter.get_suppression_factor("fresh_key"), 0.0);

What this quickstart proves

  • Local limiting needs no external services.
  • build() starts cleanup automatically, while new(...) does not.
  • Absolute gives read-style (is_allowed) and write-style (inc) checks.
  • Suppressed mode exposes current pressure through get_suppression_factor(...).

Next steps