Redis Provider
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:
| Suffix | Meaning |
|---|---|
h | hash of bucket counts |
a | sorted-set index of active bucket timestamps |
w | string cache of window capacity |
t | string total count for the window |
sf | string 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

