simple redis rate limiting
Project description
rrl - Redis Rate Limiting
Very simple reusable redis-backed rate limiting code. Designed for OpenStates.org.
Configuration
rrl
, as the name implies, requires a Redis server.
rrl
is entirely configured by environment variables:
RRL_REDIS_HOST - hostname of Redis instance (default: localhost) RRL_REDIS_PORT - port of Redis instance (default: 6379) RRL_REDIS_DB - database ID to use for RRL (default: 0)
Usage
Usage can be throttled on a per-minute, per-hour, and/or per-day basis.
rrl
has the concept of a Tier
which associates a name with a set of limitations, for instance:
# create two tiers
bronze = Tier(name="bronze", per_minute=1, per_hour=0, per_day=500)
silver = Tier(name="silver", per_minute=5, per_hour=0, per_day=4000)
These tiers do not use the per_hour feature, but will limit users to 1 or 5 requests per minute respectively. There's also a daily limit at 500 or 4000 requests per day.
Then you'll need an instance of rrl.RateLimiter
, which will be instantiated with these tiers:
limiter = RateLimiter(tiers=[bronze, silver])
Then to apply limiting, you'll call the check_limit
function, which takes three parameters:
key
- A unique-per user key, often the user's API key or username. (Note:rrl
does not know if a key is valid or not, that validation should be in your application and usually occur before the call tocheck_limit
.)tier_name
- The name of one of the tiers as specified when instantiating theRateLimiter
class. (Note:rrl
does not have a concept of which users are in which tier, that logic should be handled by your key validation code.)
Example call:
limiter.check_limit(key="1234", tier_name="bronze")
This call will return without any error if the call is deemed allowed.
If any of the rate limits are exceeded it will instead raise a RateLimitExceeded
exception describing which limit was exceeded.
If multiple limits were exceeded it will return the shortest limit violated.
Advanced Usage
Obtaining Usage Information
Your RateLimiter
instance also has a method named get_usage_since
, which takes four parameters:
key
- Which key you're requesting usage information for.start
- Date that you'd like usage since, as adatetime.date
object.end
- Optional end date if you'd only like usage within a certain window, otherwise the current day is used.
This will return a list of DailyUsage
dataclasses with the following attributes:
date
-datetime.date
calls
- Number of calls made on that date.
This method can be useful for showing users an overview of their data.
Advanced Configuration
When instantiating a RateLimiter
there are several keyword-only parameters you may set:
prefix
Passing a prefix like:
limiter = RateLimiter(tiers, prefix="v1")
will scope all calls to limiter to a given prefix, this can be useful if you want multiple limiters but want to ensure that they do not interfere with one another.
use_redis_time
True
by default, but if you set to False
the application's system time will be used instead.
The tradeoff here is one fewer call to Redis per call to check_limit
, but if your machines experience any clock drift unexpected results may occur.
track_daily_usage
True
by default, but if set to False
, rrl
will not store the necessary information to make get_usage_since
work. This results in a slight overhead reduction, but the usage information will not be stored in Redis and will be impossible to retrieve.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.