Rate limiting strategies¶
djlimiter comes with three different rate limiting strategies built-in. Pick
the one that works for your use-case by specifying it in your django settings as
RATELIMIT_STRATEGY
(one of fixed-window
, fixed-window-elastic-expiry
,
or moving-window
). The default configuration is fixed-window
.
Fixed Window¶
This is the most memory efficient strategy to use as it maintains one counter per resource and rate limit. It does however have its drawbacks as it allows bursts within each window - thus allowing an ‘attacker’ to by-pass the limits. The effects of these bursts can be partially circumvented by enforcing multiple granularities of windows per resource.
For example, if you specify a 100/minute
rate limit on a route, this strategy will
allow 100 hits in the last second of one window and a 100 more in the first
second of the next window. To ensure that such bursts are managed, you could add a second rate limit
of 2/second
on the same route.
Fixed Window with Elastic Expiry¶
This strategy works almost identically to the Fixed Window strategy with the exception that each hit results in the extension of the window. This strategy works well for creating large penalties for breaching a rate limit.
For example, if you specify a 100/minute
rate limit on a route and it is being
attacked at the rate of 5 hits per second for 2 minutes - the attacker will be locked
out of the resource for an extra 60 seconds after the last hit. This strategy helps
circumvent bursts.
Moving Window¶
Warning
The moving window strategy is only implemented for the redis
and in-memory
storage backends. The strategy requires using a list with fast random access which
is not very convenient to implement with a memcached storage.
This strategy is the most effective for preventing bursts from by-passing the
rate limit as the window for each limit is not fixed at the start and end of each time unit
(i.e. N/second for a moving window means N in the last 1000 milliseconds). There is
however a higher memory cost associated with this strategy as it requires N
items to
be maintained in memory per resource and rate limit.
Rate-limiting Headers¶
If the configuration is enabled, information about the rate limit with respect to the route being requested will be added to the response headers. Since multiple rate limits can be active for a given route - the rate limit with the lowest time granularity will be used in the scenario when the request does not breach any rate limits.
X-RateLimit-Limit |
The total number of requests allowed for the active window |
X-RateLimit-Remaining |
The number of requests remaining in the active window. |
X-RateLimit-Reset |
UTC seconds since epoch when the window will be reset. |
Warning
Enabling the headers has an additional cost with certain storage / strategy combinations.
- Memcached + Fixed Window: an extra key per rate limit is stored to calculate
X-RateLimit-Reset
- Redis + Moving Window: an extra call to redis is involved during every request
to calculate
X-RateLimit-Remaining
andX-RateLimit-Reset
The header names can be customised if required by using django settings (Configuration).