Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ramgate

High-throughput, concurrent sliding window counter rate limiter for Rust.

Zero dependencies. Pure sync core. True zero-allocation hot path. Deterministic testing via mock clock.

Features

  • Sliding window counter — weighted previous/current window, eliminates boundary bursts
  • True zero-allocation hot path — get_mut on existing keys, no heap traffic
  • Exact retry_after — mathematically precise intra- and inter-window decay
  • HashDoS resistant — SipHash-1-3 via stdlib RandomState by default
  • Saturating time arithmetic — clock skew and NTP step safe
  • Accurate idle eviction — tracks precise last_seen per key
  • Cost-aware admission — consume N units per check
  • Sharded concurrency — parallel key access, no cross-shard contention
  • Deterministic testing — mock clock without thread sleeping
  • Zero dependencies — pure stdlib, no async runtime required

Usage

[dependencies]
ramgate = "0.2"
use ramgate::RateLimiter;
use std::time::Duration;

// 100 requests per 60-second window, 16 shards
let limiter = RateLimiter::new(100, Duration::from_secs(60));

assert!(limiter.allow("ip:127.0.0.1"));
assert!(limiter.allow("ip:127.0.0.1"));

// Cost-aware: consume 5 units at once
let result = limiter.check_n("ip:10.0.0.1", 5);
assert!(result.is_ok());

Deterministic testing

use ramgate::{RateLimiter, FakeClock};
use std::time::Duration;

let clock = FakeClock::new();
let limiter = RateLimiter::with_clock(5, Duration::from_secs(10), clock.clone());

for _ in 0..5 {
    assert!(limiter.allow("key"));
}
assert!(!limiter.allow("key"));

// Advance past window boundary, then into new window
clock.advance(Duration::from_secs(10)); // rotation: previous=5, current=0
clock.advance(Duration::from_secs(5));  // previous_weight=0.5, weighted=2.5
assert!(limiter.allow("key")); // 2.5+1=3.5 <= 5

Custom hasher

Use FnvBuilder for high-throughput trusted environments (not HashDoS-safe):

use ramgate::{RateLimiter, FnvBuilder};
use std::time::Duration;

let limiter = RateLimiter::with_hasher(
    100,
    Duration::from_secs(60),
    16,
    ramgate::WallClock,
    FnvBuilder,
);

Algorithm

Sliding window counter: two fixed windows (current + previous), weighted sum. No boundary bursts. O(1) per check. O(1) amortized eviction.

Property Value
Check O(1)
Memory per key 32 bytes (2 u64 + 2 Instant) + key allocation
Shard count Power of 2 (default: 16)
Default hasher SipHash-1-3 (HashDoS resistant)
Dependencies Zero

License

MIT OR Apache-2.0

About

Concurrent sliding window counter rate limiter for Rust. Zero-alloc hot path, exact retry_after, HashDoS-safe, saturating time arithmetic. Pure stdlib, no dependencies.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages