Providers

Redis Provider

Distributed rate limiting backed by Redis 6.2+.

The Redis provider enables distributed rate limiting across multiple processes or servers using Redis as a shared backend.

Access it through RateLimiter::redis().

use std::sync::Arc;

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

// Create Redis connection manager
let client = redis::Client::open("redis://127.0.0.1:6379/").unwrap();
let connection_manager = client.get_connection_manager().await.unwrap();

let rl = Arc::new(RateLimiter::new(RateLimiterOptions {
    local: LocalRateLimiterOptions {
        window_size_seconds: WindowSizeSeconds::try_from(60).unwrap(),
        rate_group_size_ms: RateGroupSizeMs::try_from(10).unwrap(),
        hard_limit_factor: HardLimitFactor::default(),
        suppression_factor_cache_ms: SuppressionFactorCacheMs::default(),
    },
    redis: RedisRateLimiterOptions {
        connection_manager,
        prefix: None,
        window_size_seconds: WindowSizeSeconds::try_from(60).unwrap(),
        rate_group_size_ms: RateGroupSizeMs::try_from(10).unwrap(),
        hard_limit_factor: HardLimitFactor::default(),
        suppression_factor_cache_ms: SuppressionFactorCacheMs::default(),
    },
}));

let redis = rl.redis();
let _ = redis;

Requirements:

You need Redis >= 6.2 and an async runtime: Tokio (redis-tokio) or Smol (redis-smol).

Data model (high level)

Redis operations are implemented as Lua scripts.

For each user key ("entity"), the limiter stores a small set of Redis keys under a prefix (default: trypema).

Key schema

All per-entity keys follow this pattern:

<prefix>:<entity>:<rate_type>:<suffix>

Where:

<rate_type> is one of absolute, suppressed, suppressed_observed. <suffix> identifies the data structure:

SuffixMeaning
hhash of bucket counts
asorted-set index of active bucket timestamps
wstring cache of window capacity
tstring total count for the window
sfstring suppression-factor cache (suppressed only)

There is also a shared key used for cleanup:

<prefix>:active_entities

This is a sorted set where members are entities and scores are last-seen timestamps.

Semantics

Each Lua script execution is atomic in Redis.

For inc(...) on the absolute strategy, the admission check and increment happen inside the same Lua script, so concurrent callers for the same key do not overshoot due to races.

If you perform a separate is_allowed(...) check and then later call inc(...), that check-then-act pattern is not atomic.

Key constraints

Redis keys are validated and must not contain :.

use trypema::redis::RedisKey;

let _ = RedisKey::try_from("user_123".to_string()).unwrap();
let _ = RedisKey::try_from("user:123".to_string());

Cleanup behavior

The Redis provider supports proactive cleanup via RateLimiter::run_cleanup_loop(). Cleanup uses the <prefix>:active_entities index to delete per-entity keys that have been inactive longer than stale_after_ms.

Redis Cluster note

Redis Cluster is not a primary target. Lua scripts touching multiple keys require keys to be co-located on the same hash slot.

If you need cluster support, validate your deployment early and consider filing an issue with your constraints.

More detail

See the full Redis implementation notes on GitHub:

https://github.com/dev-davexoyinbo/trypema/blob/main/docs/redis.md