Token bucket and sliding window rate limiter library for TypeScript/Node.js. Two battle-tested algorithms behind a single unified interface, with zero external dependencies.
Rate limiting is foundational infrastructure for APIs, job queues, and any system that needs to control throughput. This library provides two complementary algorithms � token bucket (smooth, burst-tolerant) and sliding window counter (strict, window-based) � both injectable with custom clocks for deterministic testing.
npm install rate-limiterOr install from source:
git clone https://github.com/nripankadas07/rate-limiter.git
cd rate-limiter
npm install && npm run buildimport { RateLimiter } from "rate-limiter";
// Token bucket: 100 requests, refilling 10/sec
const limiter = new RateLimiter({
strategy: "token-bucket",
capacity: 100,
refillRate: 10,
});
const result = limiter.limit();
if (result.allowed) {
console.log(`Allowed. ${result.remaining} remaining.`);
} else {
console.log(`Rate limited. Retry after ${result.retryAfter}ms.`);
}Best for APIs where you want to allow short bursts while maintaining an average rate.
import { TokenBucket } from "rate-limiter";
const bucket = new TokenBucket({
capacity: 50, // max burst size
refillRate: 10, // tokens per second
});
if (bucket.consume()) {
// Request allowed
}
// Consume multiple tokens (e.g., for weighted requests)
bucket.consume(5);
// Check without consuming
console.log(bucket.getAvailableTokens());
// How long until 3 tokens are available?
console.log(bucket.getRetryAfter(3)); // millisecondsBest for strict per-window limits (e.g., "100 requests per minute").
import { SlidingWindowCounter } from "rate-limiter";
const window = new SlidingWindowCounter({
limit: 100, // max requests per window
windowMs: 60_000, // 1 minute window
});
if (window.consume()) {
// Request allowed
}
console.log(window.getRemaining()); // requests left
console.log(window.getRetryAfter()); // ms until resetBoth algorithms accept a clock function for deterministic tests:
let now = 0;
const clock = () => now;
const bucket = new TokenBucket({ capacity: 5, refillRate: 1, clock });
bucket.consume(); // 4 remaining
now += 2000; // advance 2 seconds
bucket.getAvailableTokens(); // 5 (refilled, capped at capacity)Unified wrapper for both strategies.
new RateLimiter(options)� Create with{ strategy: "token-bucket", ...bucketOpts }or{ strategy: "sliding-window", ...windowOpts }.limit(count?)� ReturnsRateLimitResult { allowed, remaining, retryAfter }.reset()� Reset all state.
consume(count?)� Consume tokens. Returnsboolean.getAvailableTokens()� Current token count.getRetryAfter(count?)� Milliseconds until tokens are available.reset()� Refill to capacity.
consume()� Record a request. Returnsboolean.getEstimatedCount()� Weighted request count in the sliding window.getRemaining()� Remaining requests allowed.getRetryAfter()� Milliseconds until the window shifts enough.reset()� Clear all counters.
src/
��� token-bucket.ts # Token bucket algorithm with refill logic
��� sliding-window.ts # Sliding window counter with interpolation
��� rate-limiter.ts # Unified interface wrapping both strategies
��� index.ts # Public exports
The token bucket uses a lazy refill pattern � tokens are calculated on demand based on elapsed time, not with timers. The sliding window counter uses weighted interpolation between the current and previous window for a smooth approximation without per-request timestamps. Both are O(1) per operation with zero allocations on the hot path.
MIT License � Copyright 2024 Nripanka Das