View Source Hammer.ETS.TokenBucket (hammer v7.0.0-rc.3)
This module implements the Token Bucket algorithm. The token bucket algorithm works by modeling a bucket that:
- Fills with tokens at a constant rate (the refill rate)
- Has a maximum capacity of tokens (the bucket size)
- Each request consumes one or more tokens
- If there are enough tokens, the request is allowed
- If not enough tokens, the request is denied
For example, with a refill rate of 10 tokens/second and bucket size of 100:
- Tokens are added at 10 per second up to max of 100
- Each request needs tokens to proceed
- If bucket has enough tokens, request allowed and tokens consumed
- If not enough tokens, request denied until bucket refills
The algorithm:
- When a request comes in, we:
- Calculate tokens added since last request based on time elapsed
- Add new tokens to bucket (up to max capacity)
- Try to consume tokens for the request
- Store new token count and timestamp
- To check if rate limit is exceeded:
- If enough tokens: allow request and consume tokens
- If not enough: deny and return time until enough tokens refill
- Old entries are automatically cleaned up after expiration
This provides smooth rate limiting with ability to handle bursts up to bucket size. The token bucket is a good choice when:
- You need to allow temporary bursts of traffic
- Want to enforce an average rate limit
- Need to support different costs for different operations
- Want to avoid the sharp edges of fixed windows
Common use cases include:
- API rate limiting with burst tolerance
- Network traffic shaping
- Resource allocation control
- Gaming systems with "energy" mechanics
- Scenarios needing flexible rate limits
The main advantages are:
- Natural handling of bursts
- Flexible token costs for different operations
- Smooth rate limiting behavior
- Simple to reason about
The tradeoffs are:
- Need to track token count and last update time
- May need tuning of bucket size and refill rate
- More complex than fixed windows
For example with 100 tokens/minute limit and 500 bucket size:
- Can handle bursts using saved up tokens
- Automatically smooths out over time
- Different operations can cost different amounts
- More flexible than fixed request counts
The token bucket algorithm supports the following options:
:clean_period
- How often to run the cleanup process (in milliseconds) Defaults to 1 minute. The cleanup process removes expired bucket entries.:key_older_than
- Optional maximum age for bucket entries (in milliseconds) If set, entries older than this will be removed during cleanup. This helps prevent memory growth from abandoned buckets.
Example configuration:
MyApp.RateLimit.start_link(
clean_period: :timer.minutes(5),
key_older_than: :timer.hours(24)
)
This would run cleanup every 5 minutes and remove buckets not used in 24 hours.
Summary
Functions
Cleans up all of the old entries from the table based on the key_older_than
option.
Returns the current level of the bucket for a given key.
Functions
@spec clean(config :: Hammer.ETS.config()) :: non_neg_integer()
Cleans up all of the old entries from the table based on the key_older_than
option.
@spec get(table :: atom(), key :: String.t()) :: non_neg_integer()
Returns the current level of the bucket for a given key.