Skip to content

Instantly share code, notes, and snippets.

@jazibsawar
Last active February 18, 2025 22:33
Show Gist options
  • Save jazibsawar/ce8aa2afa09877d31742591021856cd2 to your computer and use it in GitHub Desktop.
Save jazibsawar/ce8aa2afa09877d31742591021856cd2 to your computer and use it in GitHub Desktop.
Implementation of leaky bucket rate limiter in TS
/*
The algorithm is simple:
Assume a bucket that can hold a limited amount of water (requests). Over time, water leaks out at a fixed rate,
creating space for new water. A new request (water) is only accepted if there is enough free space in the bucket;
otherwise, it is denied.
*/
class LeakyBucketRateLimiter {
private bucketCapacity: number;
private currentBucketSize: number;
private bucketLeakRate: number;
private lastUpdate: number;
constructor(capacity: number, leakRate: number) {
// Maximum capacity of the bucket (requests allowed)
this.bucketCapacity = capacity;
// Currently, consumed bucket size
this.currentBucketSize = 0;
// The rate at which the bucket is leaking
this.bucketLeakRate = leakRate;
// Timestamp of last update
this.lastUpdate = Date.now();
}
private leak(): void {
const timeNow = Date.now();
const timeSinceLastUpdate = (timeNow - this.lastUpdate) / 1000; // seconds
const tokensToLeak = timeSinceLastUpdate * this.bucketLeakRate;
this.currentBucketSize = Math.max(0, this.currentBucketSize - tokensToLeak);
this.lastUpdate = timeNow;
}
public consume(requests = 1): boolean {
this.leak();
// Only allow if current bucket size + requests will not overflow the bucket
if (this.currentBucketSize + requests <= this.bucketCapacity) {
this.currentBucketSize = this.currentBucketSize + requests;
return true;
}
return false;
}
}
// Test cases
const testLimiter = new LeakyBucketRateLimiter(5, 1);
// Should not allow more requests than capacity
console.assert(testLimiter.consume(6) === false, "Deny requests if over capacity);
console.assert(testLimiter.consume() === true, "First request should be allowed");
console.assert(testLimiter.consume(4) === true, "Should allow up to capacity");
console.assert(testLimiter.consume(1) === false, "Deny request exceeding capacity");
setTimeout(() => {
console.assert(testLimiter.consume() === true, "After leakage, request should be allowed");
}, 1500); // The rate is 1req/sec.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment