philiprehberger_rate_limiter
In-process rate limiter with token bucket and sliding window algorithms
Requirements
- Elixir >= 1.14
- OTP >= 25
Installation
Add to your mix.exs dependencies:
def deps do
[
{:philiprehberger_rate_limiter, "~> 0.1.0"}
]
endThen run:
mix deps.getUsage
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}
endToken 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 testSupport
If you find this project useful: