| Crates.io | actix-limiter |
| lib.rs | actix-limiter |
| version | 0.1.0 |
| created_at | 2025-08-04 04:25:31.9975+00 |
| updated_at | 2025-08-04 04:25:31.9975+00 |
| description | Rate limiter using a fixed window counter for arbitrary keys, created for Actix Web |
| homepage | |
| repository | https://github.com/meszmate/actix-limiter |
| max_upload_size | |
| id | 1780289 |
| size | 74,300 |
Rate-limiting middleware for Actix-web backed by a single Redis Lua script.
The Lua script (EVAL) is sent to Redis once.
A pipeline of MULTI / SET / INCR / TTL / EXEC still requires three round-trips.
That’s ~1 ms vs. ~3 ms on a remote Redis.
Lua runs inside the Redis server.
No WATCH/MULTI juggling and no window where two requests can double-increment the counter.
A single 15-line Lua block replaces a 5-command pipeline, making the Rust side shorter, clearer, and easier to test.
Benchmarks at 60 k RPS:
—just less network usage.
Deadpool-Redis reuses connections, so your app can handle way more requests without opening a new Redis link every time. Fast, efficient, and built for async Rust.
Only redis-rs / deadpool-redis. No extra crates, no unsafe, no macro magic.
Use Lua when you want the lowest latency and simplest code; use the pipeline only when you deliberately need plain Redis commands.
use actix_web::{web, App, HttpServer};
use std::sync::Arc;
use std::time::Duration;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// 1. Build a Redis pool
let cfg = deadpool_redis::Config::from_url("redis://127.0.0.1:6379");
let pool = cfg.create_pool(Some(deadpool_redis::Runtime::Tokio1)).unwrap();
// 2. Build the limiter
let limiter = Arc::new(
actix_limiter::Limiter::builder(Arc::new(pool))
.limit(60)
.period(Duration::from_secs(60))
.key_by(|req| Some(req.connection_info().realip_remote_addr()?.to_string()))
.build()
.unwrap(),
);
// 3. Wrap only the routes you want
HttpServer::new(move || {
App::new()
.app_data(web::Data::from(limiter.clone()))
.service(
web::scope("/api")
.wrap(actix_limiter::RateLimiter)
.route("/hello", web::get().to(|| async { "hello" })),
)
})
.bind("0.0.0.0:8080")?
.run()
.await
}