Troubleshooting
Start with these checks:
- Confirm your
RateLimitand config newtypes are valid (try_from(...)does validation). - For Redis provider, confirm Redis >= 6.2 and that all instances use identical provider options.
- For suppressed decisions, always gate on
is_allowed(not just the enum variant).
Redis connection refused
Check that Redis is running and reachable, and that REDIS_URL points to the right host/port.
Also check Redis version (must be >= 6.2):
redis-cli INFO server | grep redis_version
Redis key validation fails
If you see TrypemaError::InvalidRedisKey, validate your input key:
It must be non-empty, <= 255 bytes, and must not contain :.
If you need a compound key, use a different separator like _ or |.
Validation errors when constructing types
Many configuration and input types are validated newtypes.
Common failures:
RateLimit::try_from(value)fails ifvalue <= 0.WindowSizeSeconds::try_from(value)fails ifvalue < 1.RateGroupSizeMs::try_from(value)fails ifvalue < 1.SuppressionFactorCacheMs::try_from(value)fails ifvalue == 0.
Cleanup loop doesn't seem to run (Tokio)
If you're using redis-tokio, Redis cleanup is spawned on the current Tokio runtime.
Check that you're calling run_cleanup_loop() from within a Tokio runtime context, and that you haven't dropped all Arc<RateLimiter> references (cleanup uses Weak).
Weak<RateLimiter>, not a strong Arc. If you drop all Arc<RateLimiter> references, the loop exits by itself.Memory usage grows over time
Check key cardinality, whether run_cleanup_loop() is enabled (local provider), and whether you need external Redis key cleanup (Redis provider).
If memory growth is attacker-driven, limit key cardinality at the edge (normalize, rate limit earlier, or require authentication).
Suppressed decisions are mishandled
If you use the suppressed strategy, RateLimitDecision::Suppressed is not automatically a denial.
Gate on is_allowed:
use trypema::RateLimitDecision;
match decision {
RateLimitDecision::Allowed => {}
RateLimitDecision::Suppressed { is_allowed: true, .. } => {
// admitted (often degrade priority)
}
RateLimitDecision::Suppressed { is_allowed: false, .. } => {
// suppressed: treat like denial
}
RateLimitDecision::Rejected { .. } => {
// over hard limit
}
}
If you want to admit-and-record, call inc(...) directly and use its returned decision.
Inconsistent behavior across instances
For Redis provider deployments, ensure every instance uses the same provider options:
window_size_seconds, rate_group_size_ms, hard_limit_factor, and suppression_factor_cache_ms.
Mixed configs can produce surprising admission decisions.
Redis provider doesn't compile
The Redis provider is behind feature flags.
- Enable
redis-tokio(Tokio) orredis-smol(Smol). - Ensure your async runtime is present and you are calling Redis methods from an async context.

