Rate Limiting in Rust: Libraries for Request Frequency Limiting

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Rate Limiting in Rust: Efficient Load Management



Rate limiting is a key mechanism for protecting and optimizing web services, APIs, and network applications. In the Rust ecosystem, there are several mature libraries implementing various algorithms: from the classic token bucket to modern adaptive methods. In this article, we will cover three main libraries: governor, leaky-bucket, and ratelimit, with code examples and recommendations for selection.



1. The governor Library — The Gold Standard



governor is the most popular and flexible library for rate limiting. It implements the Generic Cell Rate Algorithm (GCRA), which ensures precise adherence to limits with minimal latency. It supports synchronous and asynchronous modes, as well as middleware for Actix-web, Axum, and Rocket.



Basic example with governor

use governor::{DefaultKeyedRateLimiter, Quota, RateLimiter};use std::num::NonZeroU32;use std::time::Duration;

fn main() { // Allow 5 requests per second let quota = Quota::per_second(NonZeroU32::new(5).unwrap()); let limiter = RateLimiter::direct(quota);

for i in 0..10 { match limiter.check() { Ok(_) => println!("Request {} allowed", i), Err(_) => println!("Request {} denied (rate limit)", i), } std::thread::sleep(Duration::from_millis(100)); }}


Asynchronous variant with waiting

use governor::{Quota, RateLimiter};use std::num::NonZeroU32;use tokio::time::{sleep, Duration};

#[tokio::main]async fn main() { let limiter = RateLimiter::direct(Quota::per_second( NonZeroU32::new(2).unwrap(), ));

for i in 0..5 { limiter.until_ready().await; println!("Processed request {}", i); sleep(Duration::from_millis(300)).await; }}


Key features of governor:

  • Support for keyed limits (per-IP, per-user) via KeyedRateLimiter
  • Integration with tower middleware for HTTP servers
  • Configurable strategies: wait, deny, adaptive slowdown
  • Minimal memory consumption (one atomic counter per limiter)


2. The leaky-bucket Library — Simplicity and Reliability



leaky-bucket implements the classic "leaky bucket" algorithm. It is ideal for smoothing out peak loads when a uniform flow of requests needs to be guaranteed. The library is lightweight and requires no external dependencies.



Example with leaky-bucket

use leaky_bucket::RateLimiter;use std::time::Duration;

#[tokio::main]async fn main() { let limiter = RateLimiter::builder() .initial(10) // initial token supply .interval(Duration::from_secs(1)) // refill interval .refill(5) // how many tokens to add per interval .max(20) // maximum number of tokens .build();

for i in 0..15 { limiter.acquire_one().await; println!("Request {} completed", i); }}


Features of leaky-bucket:

  • Support for asynchronous and blocking API
  • Ability to configure "burst" mode (short-term spikes)
  • Automatic token release during idle periods


3. The ratelimit Library — A Minimalist Approach



ratelimit is the simplest library, implementing a sliding window with fixed intervals. It is suitable for simple scenarios where high precision is not required.



Example with ratelimit

use ratelimit::Ratelimiter;use std::time::Duration;

fn main() { let mut limiter = Ratelimiter::builder(10, Duration::from_secs(1)) .

Recommendations