Prorate is a throttling/rate limiting library based on the Leaky Bucket algorithm implemented as a Lua script in Redis. This enables coordinated throttling of traffic coming into many different web servers, which is much more tricky with an in-process implementation. The algorithm is designed in such a way as to keep Redis memory use as minimal as possible.
There is also a Ruby variant of Prorate available here, made and maintained by the lovely people at WeTransfer.
Add this to your application's shard.yml
:
dependencies:
prorate:
github: wjwh/prorate
This shard defines a method called with_throttle!
that you can use to rate limit almost anything. For example to limit the rate at which any IP can call the /login
endpoint in a kemal application you can use something like the following:
require "prorate"
require "kemal"
post "/login" do |env|
with_throttle(name: "login-throttle", bucket_capacity: 3, leak_rate: 0.1, block_for: 10) do |t|
t << env.request.remote_ip
end
# rest of login logic here
rescue Prorate::Throttled
halt env, status_code: 429, response: "Too many login attempts in short succession."
end
This sets up a throttle that will allow up to three requests in quick succession. However, after three request the "bucket" is full and further requests will overflow it, leading to a Prorate::Throttled
exception being raised for this request and any further requests within block_for
seconds. The bucket will only drain at a rate of one request per ten seconds, the leak_rate
, so that is the maximum rate of requests that can be sustained without running into the Prorate::Throttled
exception. This way you can allow for a user eg mistyping their password once or twice without hitting the lockout, but can still make sure that brute force attacks are not feasible.
Running the test suite requires a running Redis server. By default it will try the default location (ie localhost:6379
), but you can override this by supplying a REDIS_URL
environment variable if you want to test against a redis server in another location.
- Fork it ( https://github.com/[your-github-name]/prorate/fork )
- Create your feature branch (git checkout -b my-new-feature)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin my-new-feature)
- Create a new Pull Request
- wjwh Wander Hillen - creator, maintainer