How to choose the optimal `numBuckets`
mainThe numBuckets parameter determines how many internal buckets are used to distribute rate limits across different IDs. The library automatically rounds this value up to the nearest power of two for efficient hashing.
Key Concepts
- Bucket Selection: The library hashes the ID (using
hash/maphash) and useshash & (numBuckets - 1)to select a bucket. - Collisions: When two IDs map to the same bucket, they share the same rate limit. While the probability of at least one collision is high, the percentage of IDs affected is what matters for system fairness.
- Load Factor: To keep the impact of collisions below 5% of your total IDs, aim to maintain a load factor (IDs / buckets) below 0.1.
Guidelines by System Size
- Small (≤100 IDs): Use 4,096 or 16,384 buckets.
- Medium (101-1,000 IDs): Use 16,384 or 65,536 buckets.
- Large (1,001-10,000 IDs): Use 65,536 or 262,144 buckets.
- Very Large (>10,000 IDs): Use 1,048,576 buckets.
Memory Usage
Memory scales linearly with numBuckets. Each bucket consumes 8 bytes (uint64).
- 65,536 buckets $\approx$ 512 KB
- 1,048,576 buckets $\approx$ 8 MB
// Example for a system with ~5,000 distinct IDs
limiter, err := rate.NewTokenBucketLimiter(
65536, // numBuckets (will remain 2^16 since it's already a power of 2) to maintain <10% collision probability
10, // burstCapacity
100, // refillRate
time.Second,
)