philiprehberger_rate_limiter

TestsHex VersionLast updated

In-process rate limiter with token bucket and sliding window algorithms

Requirements

Installation

Add to your mix.exs dependencies:

def deps do
  [
    {:philiprehberger_rate_limiter, "~> 0.1.0"}
  ]
end

Then run:

mix deps.get

Usage

Add the rate limiter to your supervision tree:

children = [
  {Philiprehberger.RateLimiter, name: :my_limiter}
]

Supervisor.start_link(children, strategy: :one_for_one)

Then check rate limits anywhere in your application:

case Philiprehberger.RateLimiter.check(:my_limiter, "user:123",
       algorithm: :token_bucket,
       capacity: 100,
       refill_rate: 10
     ) do
  {:ok, info} ->
    # Request allowed, info.remaining tokens left
    process_request()

  {:error, info} ->
    # Rate limited, retry in info.retry_after milliseconds
    {:error, :rate_limited}
end

Token Bucket

Best for APIs that allow short bursts above the average rate. Tokens refill continuously at a fixed rate.

{:ok, %{remaining: 99, limit: 100, reset_in: 1000}} =
  Philiprehberger.RateLimiter.check(:my_limiter, "user:123",
    algorithm: :token_bucket,
    capacity: 100,
    refill_rate: 10,
    cost: 1
  )

Sliding Window

Best for strict request counting per time window. Resets when the window expires.

{:ok, %{remaining: 59, limit: 60, reset_in: 58000}} =
  Philiprehberger.RateLimiter.check(:my_limiter, "ip:1.2.3.4",
    algorithm: :sliding_window,
    limit: 60,
    window: 60_000
  )

Peeking Without Consuming

Check the current status without consuming a token:

{:ok, %{remaining: 45, limit: 100}} =
  Philiprehberger.RateLimiter.peek(:my_limiter, "user:123",
    algorithm: :token_bucket,
    capacity: 100,
    refill_rate: 10
  )

Resetting Limits

# Reset a single key
:ok = Philiprehberger.RateLimiter.reset(:my_limiter, "user:123")

# Reset all keys
:ok = Philiprehberger.RateLimiter.reset_all(:my_limiter)

API

Function Description
start_link(opts) Start the rate limiter process. Requires :name option
check(limiter, key, opts) Check and consume from the rate limit. Returns {:ok, info} or {:error, info}
peek(limiter, key, opts) Check status without consuming. Returns {:ok, info}
status(limiter, key, opts) Get status as a plain map
reset(limiter, key) Reset rate limit for a specific key
reset_all(limiter) Reset all rate limits

Options

Option Algorithm Description
:algorithm Both :token_bucket or :sliding_window (required)
:capacity Token bucket Maximum number of tokens (required)
:refill_rate Token bucket Tokens added per second (required)
:cost Token bucket Tokens consumed per check (default: 1)
:limit Sliding window Maximum requests per window (required)
:window Sliding window Window size in milliseconds (required)

Development

mix deps.get
mix compile --warnings-as-errors
mix format --check-formatted
mix test

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT