Hammer.Redis.SlidingWindow (hammer_backend_redis v7.1.0)

View Source

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

Example usage:

defmodule MyApp.RateLimit do
  use Hammer, backend: Hammer.Redis, algorithm: :sliding_window
end

MyApp.RateLimit.start_link([])

# Allow 10 requests in any 1 second window
MyApp.RateLimit.hit("user_123", 1000, 10)