axum-limit
Production-oriented rate limiting for Axum with pluggable algorithms and storage backends.
Features
- Algorithms: token bucket, fixed window, sliding window counter
- Backends: in-memory (single node), Redis (multi-node,
redisfeature), custom via [RateLimitBackend] - Extractor API: declare limits in handler signatures (static or config-backed)
- Standard headers:
X-RateLimit-*andRetry-After - Verified behavior: deterministic tests +
proptest
Requirements
- MSRV: Rust 1.89
Cargo features
| Feature | Default | Description |
|---|---|---|
memory |
yes | In-memory [MemoryBackend] (single-node deployments) |
redis |
no | [RedisBackend] for shared state across nodes |
Quick start (memory backend)
use Uri;
use ;
use ;
async
async
Built-in keys
The following types implement [Key] and [StorageKey] out of the box:
- [
http::Uri] - [
http::Method] - [
http::Version] - Tuples of any types that implement both traits (e.g.
(Uri, UserId))
Custom keys must implement both [Key] (extract from the request) and [StorageKey] (serialize for storage).
Dynamic quota (from config)
Keep the algorithm fixed in the handler type and load [Quota] from application state:
use FromRef;
use ;
use Uri;
async
async
For multiple quotas in one AppState, use a marker newtype with [FromRef]:
use FromRef;
use ;
;
async
[FixedQuota] is a convenience newtype when you prefer naming the quota field explicitly in state.
Changing a quota at runtime uses a new storage fingerprint, so existing counters are not carried over.
Rate limit headers on success
Rejected requests include X-RateLimit-* and Retry-After automatically. For successful requests, read headers from request extensions:
use ;
use ;
use Uri;
async
Redis backend (multi-node)
Enable the redis feature, then use [RedisBackend] and specify it on the extractor:
#
# async
Custom backend
Implement [RateLimitBackend] and use [apply_policy] to run algorithms against your storage:
use ;
use async_trait;
;
Custom keys must implement [StorageKey] in addition to [Key].
Storage model
- Policy state is serialized as JSON under keys like
{namespace}:{policy}:{quota}:{subject} - UTC millisecond timestamps keep nodes consistent
- Different quotas on the same subject are isolated automatically via [
Quota::fingerprint] - [
Quota::burst] controls token-bucket burst capacity (defaults tomax)
Algorithms
| Algorithm | Extractor | Best for |
|---|---|---|
| Token bucket | Limit, LimitPerSecond, DynamicLimit |
Bursts with smooth sustained rate |
| Fixed window | FixedWindowLimit, DynamicFixedWindowLimit |
Lowest overhead |
| Sliding window | SlidingWindowLimit, DynamicSlidingWindowLimit |
Fair limits without window spikes |
See the basic example for a multi-algorithm setup with a unified AppState.