Ratelix 

An Elixir library that provides robust, concurrent-safe rate limiting using two classic algorithms: Leaky Bucket and Token Bucket. It is designed for use in APIs, background jobs, or anywhere you need to control the rate of operations. All that in local node context.
Features
- Leaky Bucket: Queues requests and processes them at a fixed rate. Excess requests are rejected if the bucket is full.
- Token Bucket: Allows bursts up to a set capacity, refilling tokens at a configurable rate.
- GenServer-based: Each limiter runs as a supervised process, supporting concurrency and fault-tolerance.
- Named Limiters: Start and interact with multiple independent limiters by name.
- Unified API: Interact with both algorithms using a single, simple interface.
Installation
Add ratelix to your list of dependencies in mix.exs:
def deps do
[
{:ratelix, "~> 1.0.0"}
]
endUsage
Warning
Ensure ratelix
supervisoris started.
Starting a Rate Limiter
You can start a rate limiter process with either algorithm:
Leaky Bucket
{:ok, _sup} = Ratelix.Supervisor.start_link(nil)
{:ok, _worker} = Ratelix.start_process(:client, algorithm: :leaky_bucket, capacity: 5, interval: 1):capacity- Maximum number of requests that can be queued (required):interval- Time interval in seconds over which the capacity is enforced (default: 1)
Token Bucket
{:ok, _sup} = Ratelix.Supervisor.start_link(nil)
{:ok, _worker} = Ratelix.start_process(:client, algorithm: :token_bucket, capacity: 10, rate: 2, interval: 1):capacity- Maximum number of tokens in the bucket (default: 5):rate- Number of tokens added per interval (default: 1):interval- Time interval in seconds for token refill (default: 1)
Requesting Permission
To check if an action is allowed (and update the limiter’s state):
case Ratelix.wait_for_turn(:client) do
:ok -> do_the_thing()
{:error, reason} -> handle_rate_limit(reason)
endChecking Limiter State
Ratelix.bucket_stats(:client)Example
{:ok, _worker} = Ratelix.start_process(:client, algorithm: :leaky_bucket, capacity: 10, interval: 1)
for _ <- 1..12 do
IO.inspect Ratelix.wait_for_turn(:client)
endAlgorithms
Leaky Bucket
-
Requests are queued up to
:capacity. - Requests are processed at a fixed interval.
-
If the bucket is full, new requests are rejected with
{:error, :bucket_full}.
Token Bucket
- Each request consumes a token.
-
Tokens are refilled at a fixed rate up to
:capacity. -
If no tokens are available, requests are rejected with
{:error, :no_token}.
When to Use
- Leaky Bucket: When you want a steady, constant rate of processing (e.g., smoothing out bursts).
- Token Bucket: When you want to allow short bursts but enforce an average rate over time.
Contributing
Before submitting a PR, ensure you run mix check and all checks passes
successfully.
Version Bumps
This project adheres to Semantic Versioning,
which means the version number will follow the format MAJOR.MINOR.PATCH.
Also, the github-tag-action is used to automatically create a new tag when the PR is merged to master.
When open a PR meant to generate a new version:
Update the
mix.exsandREADMEwith the new version.Update CHANGELOG with the new version tight to semantic versioning.
Don't forget to include in your commit the tag:
"#patch"for incrementPATCHversion. E.g.: "Fix failing tests (#patch)"."#minor"for incrementMINORversion. E.g.: "Add Telemetry utility to instrument the projects (#minor)"."#major"for incrementMAJORversion. E.g.: "Release x.y.z (#major)".
If for some reason GH actions are not working (maybe because we ran out of minutes), then push the tag manually, like so:
git tag -a v0.1.0 -m "Ratelix version 0.1.0"
git push origin v0.1.0License
Apache License 2.0. See the project’s LICENSE file for details.