A Redis module that provides rate limiting in Redis as a single command. Implements the fairly sophisticated generic cell rate algorithm which provides a rolling time window and doesn't depend on a background drip process.
This implementation is based on amazing projects such as:
- throttled: An implementation that can be used standalone or easily plugged into a Go HTTP stack.
- redis-cell: An implementation in Rust that can be loaded from directly within Redis as a module.
- redis-gcra: An implementation that runs in Lua from within Redis and which provides a Ruby API.
While those projects where designed to be modular and flexible this is a straightforward implementation of the GCR algorithm, in 130 lines of C, without any external dependencies.
Clone and build this project from source.
$ git clone https://github.com/onsigntv/redis-rate-limiter.git
$ cd redis-rate-limiter
$ make
$ cp ratelimit.so /path/to/modules/
Run Redis pointing to the newly built module:
redis-server --loadmodule /path/to/modules/ratelimit.so
Alternatively add the following to a redis.conf
file:
loadmodule /path/to/modules/ratelimit.so
From Redis (try running redis-cli
) use the new RATER.LIMIT
command loaded by
the module. It's used like this:
RATER.LIMIT <key> <max_burst> <count per period> <period> [<quantity>]
Where key
is an identifier to rate limit against. Examples might be:
- A user account's unique identifier.
- The origin IP address of an incoming request.
- A static string (e.g.
global
) to limit actions across the entire system.
For example:
RATER.LIMIT user123 15 30 60 1
▲ ▲ ▲ ▲ ▲
| | | | └───── apply 1 token (default if omitted)
| | └──┴─────── 30 tokens / 60 seconds
| └───────────── 15 max_burst
└─────────────────── key "user123"
This means that a single token (the 1
in the last parameter) should be
applied against the rate limit of the key user123
. 30 tokens on the key are
allowed over a 60 second period with a maximum initial burst of 15 tokens. Rate
limiting parameters are provided with every invocation so that limits can
easily be reconfigured on the fly.
The command will respond with an array of integers:
127.0.0.1:6379> RATER.LIMIT user123 15 30 60
1) (integer) 0
2) (integer) 16
3) (integer) 15
4) (integer) -1
5) (integer) 2
The meaning of each array item is:
- Whether the action was limited:
0
indicates the action is allowed.1
indicates that the action was limited/blocked.
- The total limit of the key (
max_burst
+ 1). This is equivalent to the commonX-RateLimit-Limit
HTTP header. - The remaining limit of the key. Equivalent to
X-RateLimit-Remaining
. - The number of seconds until the user should retry, and always
-1
if the action was allowed. Equivalent toRetry-After
. - The number of seconds until the limit will reset to its maximum capacity.
Equivalent to
X-RateLimit-Reset
.
Implement different types of rate limiting by using different key names:
RATER.LIMIT user123-read-rate 15 30 60
RATER.LIMIT user123-write-rate 5 10 60
This is free software under the terms of MIT the license (see the file
LICENSE
for details).