A reusable rate-limiting toolkit for actix-web.
It provides two complementary approaches:
- Adaptive limiter (
RateLimiter) Applies per-route policies with penalty levels, progressive lockout, and observability headers. - Global limiter (
global) Applies a single per-IP quota for the scope where the middleware is mounted.
- Route-prefix and method-aware policies (
RouteRule,MethodScope) - Per-policy profiles (
PolicySpec) with optional sensitive mode - Identity bucketing by IP + credential fingerprint (
X-Api-Key,Authorization,X-Device-Id) - Extra hard-limit protection
- Standard headers in rate-limited responses
PolicySpec::new(key, sensitive, base_rps, base_burst) uses requests per second (RPS), not milliseconds.
Internally:
interval_ms = ceil(1000 / base_rps)
Examples:
PolicySpec::new("auth", true, 6, 36)=>6 rps(~167msbetween requests), burst36PolicySpec::new("mcp_write", false, 120, 360)=>120 rps(~9msbetween requests), burst360
If you prefer time-based configuration, use:
PolicySpec::from_interval_ms(...)PolicySpec::from_interval_secs(...)
[dependencies]
rate_limiter = "0.1"[dependencies]
rate_limiter = { git = "https://github.com/JhonaCodes/rate-limiter" }[dependencies]
rate_limiter = { path = "../rate_limiter" }use actix_web::{App, HttpServer};
use rate_limiter::{MethodScope, PolicySpec, RateLimiter, RouteRule};
let policies = vec![
PolicySpec::new("auth", true, 5, 30),
PolicySpec::new("default", false, 20, 100),
];
let rules = vec![
RouteRule::new("auth", vec!["/v1/auth/"], MethodScope::Any),
RouteRule::new("default", vec!["/v1/"], MethodScope::Any),
];
let limiter = RateLimiter::new(policies, rules);
HttpServer::new(move || {
App::new()
.wrap(limiter.middleware())
// .configure(api::config)
});use actix_web::App;
use rate_limiter::{global, GlobalIpStrategy};
let app = App::new()
.wrap(global(1, 20, GlobalIpStrategy::RealIp));
// average 1 request/second, burst 20- Use
RateLimiterwhen you need endpoint-level rules (for example,/authstricter than/public). - Use
global(...)for a simple perimeter limit by IP. - You can combine both: global outside + adaptive inside domain routes.
When limiting/control is active, responses may include:
x-ratelimit-levelx-ratelimit-policyx-ratelimit-afterRetry-After
Returns 429 Too Many Requests with JSON payload:
{
"error": "rate_limit_exceeded",
"message": "Too many requests. Please retry later.",
"retry_after_seconds": 3
}RateLimiterPolicySpecRouteRuleMethodScopeglobalGlobalIpStrategy
cargo run --example actix_basicTest server: http://127.0.0.1:8081
- The library is domain-agnostic and does not hardcode business routes.
- Route-to-policy mapping is defined by each application.
- Designed for Rust edition 2024.