View Source Hammer.Atomic.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:

  1. 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
  2. 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
  3. 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

Returns the current level of the bucket for a given key.

Functions

@spec get(table :: atom(), key :: String.t()) :: non_neg_integer()

Returns the current level of the bucket for a given key.