A dead simple distributed rate limiting library in Elixir using Mnesia.
A distributed rate limiter with a focus on readable and well tested code.
The counter is syncronized over all connected nodes
iex(test2@127.0.0.1)19> Minirate.check_limit("download", "user_1", 100)
{:allow, 1}
iex(test1@127.0.0.1)14> Minirate.check_limit("download", "user_1", 100)
{:allow, 2}
Minirate is availabe as a package in Hex, just add it to your mix.exs
file:
def deps
[{:minirate, "~> 0.1"}]
end
and add it to your extra applications:
def applications do
[
extra_applications: [:minirate]
]
Minirate needs to be configured using Mix.Config.
For example, in config/config.exs
:
config :minirate,
mnesia_table: :rate_limiter,
expiry_ms: 60_000
cleanup_period_ms: 10_000
mnesia_table
specifies which table will Mnesia use to write the counters.
expiry_ms
specifies the counter life in millisecconds (for example to have rates like x request every 10 seconds, you would set expiry_ms
to 10_000)
cleanup_period_ms
specifies how often minirate will clean expired counters from the mnesia database
With Minirate you can rate limit any action on your application.
The module Minirate
the function check_limit(action_name, identifier, limit)
An Example:
@download_limit 1_000
def download_file(file, user_id) do
case Minirate.check_limit("download_file", user_id, @download_limit) do
{:allow, _count} ->
# Logic to download the file
{:block, _reason} ->
# Logic when the limit has been reached
{:skip, _reason} ->
# Skip will only happen if there's a problem with your nodes or mnesia setup and a count cannot be determined.
end
Minirate.Plug
can rate-limit actions in your web application using the ip address of the requester.
You can just put in the pipeline of your web application something like this:
plug Minirate.Plug, [action: action, limit: 10_000]
or for more flexibilty:
plug Minirate.Plug, [action: "custom_action", limit: 10_000] when action == :update or action == :create