View Source Hammer.ETS.SlidingWindow (hammer v7.0.0-rc.3)

This module implements the Rate Limiting Sliding Window algorithm.

The sliding window algorithm works by tracking requests within a moving time window. Unlike a fixed window that resets at specific intervals, the sliding window provides a smoother rate limiting experience by considering the most recent window of time.

For example, with a 60 second window:

  • At time t, we look back 60 seconds and count all requests in that period
  • At time t+1, we look back 60 seconds from t+1, dropping any requests older than that
  • This creates a "sliding" effect where the window gradually moves forward in time

The algorithm:

  1. When a request comes in, we store it with the current timestamp
  2. To check if rate limit is exceeded, we:
    • Count all requests within the last <scale> seconds
    • If count <= limit: allow the request
    • If count > limit: deny and return time until oldest request expires
  3. Old entries outside the window are automatically cleaned up

This provides more precise rate limiting compared to fixed windows, avoiding the edge case where a burst of requests spans a fixed window boundary.

The sliding window algorithm is a good choice when:

  • You need precise rate limiting without allowing bursts at window boundaries
  • Accuracy of the rate limit is critical for your application
  • You can accept slightly higher storage overhead compared to fixed windows
  • You want to avoid sudden changes in allowed request rates

Common use cases include:

  • API rate limiting where consistent request rates are important
  • Financial transaction rate limiting
  • User action throttling requiring precise control
  • Gaming or real-time applications needing smooth rate control
  • Security-sensitive rate limiting scenarios

The main advantages over fixed windows are:

  • No possibility of 2x burst at window boundaries
  • Smoother rate limiting behavior
  • More predictable request patterns

The tradeoffs are:

  • Slightly more complex implementation
  • Higher storage requirements (need to store individual request timestamps)
  • More computation required to check limits (need to count requests in window)

For example, with a limit of 100 requests per minute:

  • Fixed window might allow 200 requests across a boundary (100 at 11:59, 100 at 12:00)
  • Sliding window ensures no more than 100 requests in ANY 60 second period

The sliding window 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 window entries.

Example configuration:

MyApp.RateLimit.start_link(
  clean_period: :timer.minutes(5),
)

This would run cleanup every 5 minutes and clean up old windows.

Summary

Functions

Cleans up all of the old entries from the table based on the key_older_than option.

Returns the count of requests for a given key

Checks if a key is allowed to perform an action based on the sliding window algorithm.

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(), scale :: pos_integer()) ::
  non_neg_integer()

Returns the count of requests for a given key

Link to this function

hit(table, key, scale, limit)

View Source
@spec hit(
  table :: atom(),
  key :: String.t(),
  scale :: pos_integer(),
  limit :: pos_integer()
) :: {:allow, non_neg_integer()} | {:deny, non_neg_integer()}

Checks if a key is allowed to perform an action based on the sliding window algorithm.