API Reference

limits

Rate limiting with commonly used storage backends

limits.strategies

Rate limiting strategies

limits.storage

Implementations of storage backends to be used with limits.strategies.RateLimiter strategies

limits.aio.strategies

Asynchronous rate limiting strategies

limits.aio.storage

Implementations of storage backends to be used with limits.aio.strategies.RateLimiter strategies

Strategies

Synchronous Strategies

The available built in rate limiting strategies which expect a single parameter: a subclass of Storage.

Provided by limits.strategies

class FixedWindowRateLimiter(storage: Storage | limits.aio.storage.Storage)[source]

Reference: Fixed Window

hit(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Consume the rate limit

Parameters:
  • item – The rate limit item

  • identifiers – variable list of strings to uniquely identify this instance of the limit

  • cost – The cost of this hit, default 1

test(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Check if the rate limit can be consumed

Parameters:
  • item – The rate limit item

  • identifiers – variable list of strings to uniquely identify this instance of the limit

  • cost – The expected cost to be consumed, default 1

get_window_stats(item: RateLimitItem, *identifiers: str) WindowStats[source]

Query the reset time and remaining amount for the limit

Parameters:
  • item – The rate limit item

  • identifiers – variable list of strings to uniquely identify this instance of the limit

Returns:

(reset time, remaining)

class FixedWindowElasticExpiryRateLimiter(storage: Storage | limits.aio.storage.Storage)[source]

Reference: Fixed Window with Elastic Expiry

hit(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Consume the rate limit

Parameters:
  • item – The rate limit item

  • identifiers – variable list of strings to uniquely identify this instance of the limit

  • cost – The cost of this hit, default 1

get_window_stats(item: RateLimitItem, *identifiers: str) WindowStats

Query the reset time and remaining amount for the limit

Parameters:
  • item – The rate limit item

  • identifiers – variable list of strings to uniquely identify this instance of the limit

Returns:

(reset time, remaining)

test(item: RateLimitItem, *identifiers: str, cost: int = 1) bool

Check if the rate limit can be consumed

Parameters:
  • item – The rate limit item

  • identifiers – variable list of strings to uniquely identify this instance of the limit

  • cost – The expected cost to be consumed, default 1

class MovingWindowRateLimiter(storage: Storage | limits.aio.storage.Storage)[source]

Reference: Moving Window

hit(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Consume the rate limit

Parameters:
  • item – The rate limit item

  • identifiers – variable list of strings to uniquely identify this instance of the limit

  • cost – The cost of this hit, default 1

Returns:

(reset time, remaining)

test(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Check if the rate limit can be consumed

Parameters:
  • item – The rate limit item

  • identifiers – variable list of strings to uniquely identify this instance of the limit

  • cost – The expected cost to be consumed, default 1

get_window_stats(item: RateLimitItem, *identifiers: str) WindowStats[source]

returns the number of requests remaining within this limit.

Parameters:
  • item – The rate limit item

  • identifiers – variable list of strings to uniquely identify this instance of the limit

Returns:

tuple (reset time, remaining)

All strategies implement the same abstract base class:

class RateLimiter(storage: Storage | limits.aio.storage.Storage)[source]
abstract hit(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Consume the rate limit

Parameters:
  • item – The rate limit item

  • identifiers – variable list of strings to uniquely identify this instance of the limit

  • cost – The cost of this hit, default 1

abstract test(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Check the rate limit without consuming from it.

Parameters:
  • item – The rate limit item

  • identifiers – variable list of strings to uniquely identify this instance of the limit

  • cost – The expected cost to be consumed, default 1

abstract get_window_stats(item: RateLimitItem, *identifiers: str) WindowStats[source]

Query the reset time and remaining amount for the limit

Parameters:
  • item – The rate limit item

  • identifiers – variable list of strings to uniquely identify this instance of the limit

Returns:

(reset time, remaining)

Async Strategies

These variants should be used in for asyncio support. These strategies expose async variants and expect a subclass of limits.aio.storage.Storage

Provided by limits.aio.strategies

class FixedWindowRateLimiter(storage: Storage | limits.aio.storage.Storage)[source]

Reference: Fixed Window

async hit(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Consume the rate limit

Parameters:
  • item – the rate limit item

  • identifiers – variable list of strings to uniquely identify the limit

  • cost – The cost of this hit, default 1

async test(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Check if the rate limit can be consumed

Parameters:
  • item – the rate limit item

  • identifiers – variable list of strings to uniquely identify the limit

  • cost – The expected cost to be consumed, default 1

async get_window_stats(item: RateLimitItem, *identifiers: str) WindowStats[source]

Query the reset time and remaining amount for the limit

Parameters:
  • item – the rate limit item

  • identifiers – variable list of strings to uniquely identify the limit

Returns:

reset time, remaining

class FixedWindowElasticExpiryRateLimiter(storage: Storage | limits.aio.storage.Storage)[source]

Reference: Fixed Window with Elastic Expiry

async hit(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Consume the rate limit

Parameters:
  • item – a limits.limits.RateLimitItem instance

  • identifiers – variable list of strings to uniquely identify the limit

  • cost – The cost of this hit, default 1

async get_window_stats(item: RateLimitItem, *identifiers: str) WindowStats

Query the reset time and remaining amount for the limit

Parameters:
  • item – the rate limit item

  • identifiers – variable list of strings to uniquely identify the limit

Returns:

reset time, remaining

async test(item: RateLimitItem, *identifiers: str, cost: int = 1) bool

Check if the rate limit can be consumed

Parameters:
  • item – the rate limit item

  • identifiers – variable list of strings to uniquely identify the limit

  • cost – The expected cost to be consumed, default 1

class MovingWindowRateLimiter(storage: Storage | limits.aio.storage.Storage)[source]

Reference: Moving Window

async hit(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Consume the rate limit

Parameters:
  • item – the rate limit item

  • identifiers – variable list of strings to uniquely identify the limit

  • cost – The cost of this hit, default 1

async test(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Check if the rate limit can be consumed

Parameters:
  • item – the rate limit item

  • identifiers – variable list of strings to uniquely identify the limit

  • cost – The expected cost to be consumed, default 1

async get_window_stats(item: RateLimitItem, *identifiers: str) WindowStats[source]

returns the number of requests remaining within this limit.

Parameters:
  • item – the rate limit item

  • identifiers – variable list of strings to uniquely identify the limit

Returns:

(reset time, remaining)

All strategies implement the same abstract base class:

class RateLimiter(storage: Storage | limits.aio.storage.Storage)[source]
abstract async hit(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Consume the rate limit

Parameters:
  • item – the rate limit item

  • identifiers – variable list of strings to uniquely identify the limit

  • cost – The cost of this hit, default 1

abstract async test(item: RateLimitItem, *identifiers: str, cost: int = 1) bool[source]

Check if the rate limit can be consumed

Parameters:
  • item – the rate limit item

  • identifiers – variable list of strings to uniquely identify the limit

  • cost – The expected cost to be consumed, default 1

abstract async get_window_stats(item: RateLimitItem, *identifiers: str) WindowStats[source]

Query the reset time and remaining amount for the limit

Parameters:
  • item – the rate limit item

  • identifiers – variable list of strings to uniquely identify the limit

Returns:

(reset time, remaining))

Storage

Storage Factory function

Provided by limits.storage

storage_from_string(storage_string: str, **options: float | str | bool) Storage | Storage[source]

Factory function to get an instance of the storage class based on the uri of the storage. In most cases using it should be sufficient instead of directly instantiating the storage classes. for example:

from limits.storage import storage_from_string

memory = from_string("memory://")
memcached = from_string("memcached://localhost:11211")
redis = from_string("redis://localhost:6379")

The same function can be used to construct the Async Storage variants, for example:

from limits.storage import storage_from_string

memory = storage_from_string("async+memory://")
memcached = storage_from_string("async+memcached://localhost:11211")
redis = storage_from_string("async+redis://localhost:6379")
Parameters:
  • storage_string – a string of the form scheme://host:port. More details about supported storage schemes can be found at Storage scheme

  • options – all remaining keyword arguments are passed to the constructor matched by storage_string.

Raises:

ConfigurationError – when the storage_string cannot be mapped to a registered limits.storage.Storage or limits.aio.storage.Storage instance.

Synchronous Storage

Provided by limits.storage

In-Memory Storage

class MemoryStorage(*args: Any, **kwargs: Any)[source]

rate limit storage using collections.Counter as an in memory storage for fixed and elastic window strategies, and a simple list to implement moving window strategy.

Parameters:

wrap_exceptions – Whether to wrap storage exceptions in limits.errors.StorageError before raising it.

STORAGE_SCHEME: List[str] | None = ['memory']

The storage schemes to register against this implementation

incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int[source]

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • elastic_expiry – whether to keep extending the rate limit window every hit.

  • amount – the number to increment by

get(key: str) int[source]
Parameters:

key – the key to get the counter value for

clear(key: str) None[source]
Parameters:

key – the key to clear rate limits for

acquire_entry(key: str, limit: int, expiry: int, amount: int = 1) bool[source]
Parameters:
  • key – rate limit key to acquire an entry in

  • limit – amount of entries allowed

  • expiry – expiry of the entry

  • amount – the number of entries to acquire

get_expiry(key: str) int[source]
Parameters:

key – the key to get the expiry for

get_num_acquired(key: str, expiry: int) int[source]

returns the number of entries already acquired

Parameters:
  • key – rate limit key to acquire an entry in

  • expiry – expiry of the entry

get_moving_window(key: str, limit: int, expiry: int) Tuple[int, int][source]

returns the starting point and the number of entries in the moving window

Parameters:
  • key – rate limit key

  • expiry – expiry of entry

Returns:

(start of window, number of acquired entries)

check() bool[source]

check if storage is healthy

reset() int | None[source]

reset storage to clear limits

DEPENDENCIES: Dict[str, Version | None] | List[str] = []

The python modules this class has a dependency on. Used to lazily populate the dependencies

Redis Storage

class RedisStorage(*args: Any, **kwargs: Any)[source]

Rate limit storage with redis as backend.

Depends on redis.

Parameters:
  • uri – uri of the form redis://[:password]@host:port, redis://[:password]@host:port/db, rediss://[:password]@host:port, redis+unix:///path/to/sock etc. This uri is passed directly to redis.from_url() except for the case of redis+unix:// where it is replaced with unix://.

  • connection_pool – if provided, the redis client is initialized with the connection pool and any other params passed as options

  • wrap_exceptions – Whether to wrap storage exceptions in limits.errors.StorageError before raising it.

  • options – all remaining keyword arguments are passed directly to the constructor of redis.Redis

Raises:

ConfigurationError – when the redis library is not available

STORAGE_SCHEME: List[str] | None = ['redis', 'rediss', 'redis+unix']

The storage scheme for redis

DEPENDENCIES: Dict[str, Version | None] | List[str] = {'redis': <Version('3.0')>}

The python modules this class has a dependency on. Used to lazily populate the dependencies

incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int[source]

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • amount – the number to increment by

get(key: str) int[source]
Parameters:

key – the key to get the counter value for

clear(key: str) None[source]
Parameters:

key – the key to clear rate limits for

acquire_entry(key: str, limit: int, expiry: int, amount: int = 1) bool[source]
Parameters:
  • key – rate limit key to acquire an entry in

  • limit – amount of entries allowed

  • expiry – expiry of the entry

  • amount – the number to increment by

get_expiry(key: str) int[source]
Parameters:

key – the key to get the expiry for

check() bool[source]

check if storage is healthy

get_moving_window(key: str, limit: int, expiry: int) Tuple[int, int]

returns the starting point and the number of entries in the moving window

Parameters:
  • key – rate limit key

  • expiry – expiry of entry

Returns:

(start of window, number of acquired entries)

reset() int | None[source]

This function calls a Lua Script to delete keys prefixed with self.PREFIX in blocks of 5000.

Warning

This operation was designed to be fast, but was not tested on a large production based system. Be careful with its usage as it could be slow on very large data sets.

Redis Cluster Storage

class RedisClusterStorage(*args: Any, **kwargs: Any)[source]

Rate limit storage with redis cluster as backend

Depends on redis.

Changed in version 2.5.0: Cluster support was provided by the redis-py-cluster library which has been absorbed into the official redis client. By default the redis.cluster.RedisCluster client will be used however if the version of the package is lower than 4.2.0 the implementation will fallback to trying to use rediscluster.RedisCluster.

Changed in version 3.14.0: Dropped support for the redis-py-cluster library which has been abandoned/deprecated.

Parameters:
  • uri – url of the form redis+cluster://[:password]@host:port,host:port

  • wrap_exceptions – Whether to wrap storage exceptions in limits.errors.StorageError before raising it.

  • options – all remaining keyword arguments are passed directly to the constructor of redis.cluster.RedisCluster

Raises:

ConfigurationError – when the redis library is not available or if the redis cluster cannot be reached.

STORAGE_SCHEME: List[str] | None = ['redis+cluster']

The storage scheme for redis cluster

DEFAULT_OPTIONS: Dict[str, float | str | bool] = {'max_connections': 1000}

Default options passed to the RedisCluster

DEPENDENCIES: Dict[str, Version | None] | List[str] = {'redis': <Version('4.2.0')>}

The python modules this class has a dependency on. Used to lazily populate the dependencies

acquire_entry(key: str, limit: int, expiry: int, amount: int = 1) bool
Parameters:
  • key – rate limit key to acquire an entry in

  • limit – amount of entries allowed

  • expiry – expiry of the entry

  • amount – the number to increment by

check() bool

check if storage is healthy

clear(key: str) None
Parameters:

key – the key to clear rate limits for

get(key: str) int
Parameters:

key – the key to get the counter value for

get_expiry(key: str) int
Parameters:

key – the key to get the expiry for

get_moving_window(key: str, limit: int, expiry: int) Tuple[int, int]

returns the starting point and the number of entries in the moving window

Parameters:
  • key – rate limit key

  • expiry – expiry of entry

Returns:

(start of window, number of acquired entries)

incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • amount – the number to increment by

reset() int | None[source]

Redis Clusters are sharded and deleting across shards can’t be done atomically. Because of this, this reset loops over all keys that are prefixed with self.PREFIX and calls delete on them, one at a time.

Warning

This operation was not tested with extremely large data sets. On a large production based system, care should be taken with its usage as it could be slow on very large data sets

Redis Sentinel Storage

class RedisSentinelStorage(*args: Any, **kwargs: Any)[source]

Rate limit storage with redis sentinel as backend

Depends on redis package

Parameters:
  • uri – url of the form redis+sentinel://host:port,host:port/service_name

  • service_name – sentinel service name (if not provided in uri)

  • use_replicas – Whether to use replicas for read only operations

  • sentinel_kwargs – kwargs to pass as sentinel_kwargs to redis.sentinel.Sentinel

  • wrap_exceptions – Whether to wrap storage exceptions in limits.errors.StorageError before raising it.

  • options – all remaining keyword arguments are passed directly to the constructor of redis.sentinel.Sentinel

Raises:

ConfigurationError – when the redis library is not available or if the redis master host cannot be pinged.

STORAGE_SCHEME: List[str] | None = ['redis+sentinel']

The storage scheme for redis accessed via a redis sentinel installation

DEPENDENCIES: Dict[str, Version | None] | List[str] = {'redis.sentinel': <Version('3.0')>}

The python modules this class has a dependency on. Used to lazily populate the dependencies

get(key: str) int[source]
Parameters:

key – the key to get the counter value for

get_expiry(key: str) int[source]
Parameters:

key – the key to get the expiry for

acquire_entry(key: str, limit: int, expiry: int, amount: int = 1) bool
Parameters:
  • key – rate limit key to acquire an entry in

  • limit – amount of entries allowed

  • expiry – expiry of the entry

  • amount – the number to increment by

check() bool[source]

Check if storage is healthy by calling aredis.StrictRedis.ping on the slave.

clear(key: str) None
Parameters:

key – the key to clear rate limits for

get_moving_window(key: str, limit: int, expiry: int) Tuple[int, int]

returns the starting point and the number of entries in the moving window

Parameters:
  • key – rate limit key

  • expiry – expiry of entry

Returns:

(start of window, number of acquired entries)

incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • amount – the number to increment by

reset() int | None

This function calls a Lua Script to delete keys prefixed with self.PREFIX in blocks of 5000.

Warning

This operation was designed to be fast, but was not tested on a large production based system. Be careful with its usage as it could be slow on very large data sets.

Memcached Storage

class MemcachedStorage(*args: Any, **kwargs: Any)[source]

Rate limit storage with memcached as backend.

Depends on pymemcache.

Parameters:
Raises:

ConfigurationError – when pymemcache is not available

STORAGE_SCHEME: List[str] | None = ['memcached']

The storage scheme for memcached

DEPENDENCIES: Dict[str, Version | None] | List[str] = ['pymemcache']

The python modules this class has a dependency on. Used to lazily populate the dependencies

get_client(module: ModuleType, hosts: List[Tuple[str, int]], **kwargs: str) MemcachedClientP[source]

returns a memcached client.

Parameters:
  • module – the memcached module

  • hosts – list of memcached hosts

property storage: MemcachedClientP

lazily creates a memcached client instance using a thread local

get(key: str) int[source]
Parameters:

key – the key to get the counter value for

clear(key: str) None[source]
Parameters:

key – the key to clear rate limits for

incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int[source]

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • elastic_expiry – whether to keep extending the rate limit window every hit.

  • amount – the number to increment by

get_expiry(key: str) int[source]
Parameters:

key – the key to get the expiry for

check() bool[source]

Check if storage is healthy by calling the get command on the key limiter-check

reset() int | None[source]

reset storage to clear limits

MongoDB Storage

class MongoDBStorage(*args: Any, **kwargs: Any)[source]

Changed in version 3.14.0: Added option to select custom collection names for windows & counters

Added in version 2.1.

Parameters:
  • uri – uri of the form mongodb://[user:password]@host:port?..., This uri is passed directly to MongoClient

  • database_name – The database to use for storing the rate limit collections.

  • counter_collection_name – The collection name to use for individual counters used in fixed window strategies

  • window_collection_name – The collection name to use for moving window storage

  • wrap_exceptions – Whether to wrap storage exceptions in limits.errors.StorageError before raising it.

  • options – all remaining keyword arguments are passed to the constructor of MongoClient

Raises:

ConfigurationError – when the pymongo library is not available

STORAGE_SCHEME: List[str] | None = ['mongodb', 'mongodb+srv']

The storage schemes to register against this implementation

DEPENDENCIES: Dict[str, Version | None] | List[str] = ['pymongo']

The python modules this class has a dependency on. Used to lazily populate the dependencies

acquire_entry(key: str, limit: int, expiry: int, amount: int = 1) bool
Parameters:
  • key – rate limit key to acquire an entry in

  • limit – amount of entries allowed

  • expiry – expiry of the entry

  • amount – the number of entries to acquire

check() bool

Check if storage is healthy by calling pymongo.mongo_client.MongoClient.server_info()

clear(key: str) None
Parameters:

key – the key to clear rate limits for

get(key: str) int
Parameters:

key – the key to get the counter value for

get_expiry(key: str) int
Parameters:

key – the key to get the expiry for

get_moving_window(key: str, limit: int, expiry: int) Tuple[int, int]

returns the starting point and the number of entries in the moving window

Parameters:
  • key – rate limit key

  • expiry – expiry of entry

Returns:

(start of window, number of acquired entries)

incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • amount – the number to increment by

reset() int | None

Delete all rate limit keys in the rate limit collections (counters, windows)

Etcd Storage

class EtcdStorage(*args: Any, **kwargs: Any)[source]

Rate limit storage with etcd as backend.

Depends on etcd3.

Parameters:
  • uri – etcd location of the form etcd://host:port,

  • max_retries – Maximum number of attempts to retry in the case of concurrent updates to a rate limit key

  • options – all remaining keyword arguments are passed directly to the constructor of etcd3.Etcd3Client

Raises:

ConfigurationError – when etcd3 is not available

STORAGE_SCHEME: List[str] | None = ['etcd']

The storage scheme for etcd

DEPENDENCIES: Dict[str, Version | None] | List[str] = ['etcd3']

The python modules this class has a dependency on. Used to lazily populate the dependencies

incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int[source]

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • elastic_expiry – whether to keep extending the rate limit window every hit.

  • amount – the number to increment by

get(key: str) int[source]
Parameters:

key – the key to get the counter value for

get_expiry(key: str) int[source]
Parameters:

key – the key to get the expiry for

check() bool[source]

check if storage is healthy

reset() int | None[source]

reset storage to clear limits

clear(key: str) None[source]

resets the rate limit key

Parameters:

key – the key to clear rate limits for

Async Storage

Provided by limits.aio.storage

Async In-Memory Storage

class MemoryStorage(*args: Any, **kwargs: Any)[source]

rate limit storage using collections.Counter as an in memory storage for fixed and elastic window strategies, and a simple list to implement moving window strategy.

Added in version 2.1.

Parameters:

wrap_exceptions – Whether to wrap storage exceptions in limits.errors.StorageError before raising it.

STORAGE_SCHEME: List[str] | None = ['async+memory']

The storage scheme for in process memory storage for use in an async context

async incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int[source]

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • elastic_expiry – whether to keep extending the rate limit window every hit.

  • amount – the number to increment by

async get(key: str) int[source]
Parameters:

key – the key to get the counter value for

async clear(key: str) None[source]
Parameters:

key – the key to clear rate limits for

async acquire_entry(key: str, limit: int, expiry: int, amount: int = 1) bool[source]
Parameters:
  • key – rate limit key to acquire an entry in

  • limit – amount of entries allowed

  • expiry – expiry of the entry

  • amount – the number of entries to acquire

async get_expiry(key: str) int[source]
Parameters:

key – the key to get the expiry for

async get_num_acquired(key: str, expiry: int) int[source]

returns the number of entries already acquired

Parameters:
  • key – rate limit key to acquire an entry in

  • expiry – expiry of the entry

async get_moving_window(key: str, limit: int, expiry: int) Tuple[int, int][source]

returns the starting point and the number of entries in the moving window

Parameters:
  • key – rate limit key

  • expiry – expiry of entry

Returns:

(start of window, number of acquired entries)

async check() bool[source]

check if storage is healthy

DEPENDENCIES: Dict[str, Version | None] | List[str] = []

The python modules this class has a dependency on. Used to lazily populate the dependencies

async reset() int | None[source]

reset storage to clear limits

Async Redis Storage

class RedisStorage(*args: Any, **kwargs: Any)[source]

Rate limit storage with redis as backend.

Depends on coredis

Added in version 2.1.

Parameters:
  • uri

    uri of the form:

    • async+redis://[:password]@host:port

    • async+redis://[:password]@host:port/db

    • async+rediss://[:password]@host:port

    • async+redis+unix:///path/to/sock?db=0 etc…

    This uri is passed directly to coredis.Redis.from_url() with the initial async removed, except for the case of async+redis+unix where it is replaced with unix.

  • connection_pool – if provided, the redis client is initialized with the connection pool and any other params passed as options

  • wrap_exceptions – Whether to wrap storage exceptions in limits.errors.StorageError before raising it.

  • options – all remaining keyword arguments are passed directly to the constructor of coredis.Redis

Raises:

ConfigurationError – when the redis library is not available

STORAGE_SCHEME: List[str] | None = ['async+redis', 'async+rediss', 'async+redis+unix']

The storage schemes for redis to be used in an async context

DEPENDENCIES: Dict[str, Version | None] | List[str] = {'coredis': <Version('3.4.0')>}

The python modules this class has a dependency on. Used to lazily populate the dependencies

async incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int[source]

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • amount – the number to increment by

async get(key: str) int[source]
Parameters:

key – the key to get the counter value for

async clear(key: str) None[source]
Parameters:

key – the key to clear rate limits for

async acquire_entry(key: str, limit: int, expiry: int, amount: int = 1) bool[source]
Parameters:
  • key – rate limit key to acquire an entry in

  • limit – amount of entries allowed

  • expiry – expiry of the entry

  • amount – the number of entries to acquire

async get_expiry(key: str) int[source]
Parameters:

key – the key to get the expiry for

async check() bool[source]

Check if storage is healthy by calling coredis.Redis.ping()

async reset() int | None[source]

This function calls a Lua Script to delete keys prefixed with self.PREFIX in blocks of 5000.

Warning

This operation was designed to be fast, but was not tested on a large production based system. Be careful with its usage as it could be slow on very large data sets.

async get_moving_window(key: str, limit: int, expiry: int) Tuple[int, int]

returns the starting point and the number of entries in the moving window

Parameters:
  • key – rate limit key

  • expiry – expiry of entry

Returns:

(start of window, number of acquired entries)

Async Redis Cluster Storage

class RedisClusterStorage(*args: Any, **kwargs: Any)[source]

Rate limit storage with redis cluster as backend

Depends on coredis

Added in version 2.1.

Parameters:
  • uri – url of the form async+redis+cluster://[:password]@host:port,host:port

  • options – all remaining keyword arguments are passed directly to the constructor of coredis.RedisCluster

Raises:

ConfigurationError – when the coredis library is not available or if the redis host cannot be pinged.

STORAGE_SCHEME: List[str] | None = ['async+redis+cluster']

The storage schemes for redis cluster to be used in an async context

DEFAULT_OPTIONS: Dict[str, float | str | bool] = {'max_connections': 1000}

Default options passed to coredis.RedisCluster

async reset() int | None[source]

Redis Clusters are sharded and deleting across shards can’t be done atomically. Because of this, this reset loops over all keys that are prefixed with self.PREFIX and calls delete on them, one at a time.

Warning

This operation was not tested with extremely large data sets. On a large production based system, care should be taken with its usage as it could be slow on very large data sets

DEPENDENCIES: Dict[str, Version | None] | List[str] = {'coredis': <Version('3.4.0')>}

The python modules this class has a dependency on. Used to lazily populate the dependencies

async acquire_entry(key: str, limit: int, expiry: int, amount: int = 1) bool
Parameters:
  • key – rate limit key to acquire an entry in

  • limit – amount of entries allowed

  • expiry – expiry of the entry

  • amount – the number of entries to acquire

async check() bool

Check if storage is healthy by calling coredis.Redis.ping()

async clear(key: str) None
Parameters:

key – the key to clear rate limits for

async get(key: str) int
Parameters:

key – the key to get the counter value for

async get_expiry(key: str) int
Parameters:

key – the key to get the expiry for

async get_moving_window(key: str, limit: int, expiry: int) Tuple[int, int]

returns the starting point and the number of entries in the moving window

Parameters:
  • key – rate limit key

  • expiry – expiry of entry

Returns:

(start of window, number of acquired entries)

async incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • amount – the number to increment by

Async Redis Sentinel Storage

class RedisSentinelStorage(*args: Any, **kwargs: Any)[source]

Rate limit storage with redis sentinel as backend

Depends on coredis

Added in version 2.1.

Parameters:
  • uri – url of the form async+redis+sentinel://host:port,host:port/service_name

  • optional (sentinel_kwargs,) – sentinel service name (if not provided in uri)

  • use_replicas – Whether to use replicas for read only operations

  • optional – kwargs to pass as sentinel_kwargs to coredis.sentinel.Sentinel

  • options – all remaining keyword arguments are passed directly to the constructor of coredis.sentinel.Sentinel

Raises:

ConfigurationError – when the coredis library is not available or if the redis primary host cannot be pinged.

STORAGE_SCHEME: List[str] | None = ['async+redis+sentinel']

The storage scheme for redis accessed via a redis sentinel installation

DEPENDENCIES: Dict[str, Version | None] | List[str] = {'coredis.sentinel': <Version('3.4.0')>}

The python modules this class has a dependency on. Used to lazily populate the dependencies

async acquire_entry(key: str, limit: int, expiry: int, amount: int = 1) bool
Parameters:
  • key – rate limit key to acquire an entry in

  • limit – amount of entries allowed

  • expiry – expiry of the entry

  • amount – the number of entries to acquire

async clear(key: str) None
Parameters:

key – the key to clear rate limits for

async get_moving_window(key: str, limit: int, expiry: int) Tuple[int, int]

returns the starting point and the number of entries in the moving window

Parameters:
  • key – rate limit key

  • expiry – expiry of entry

Returns:

(start of window, number of acquired entries)

async incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • amount – the number to increment by

async reset() int | None

This function calls a Lua Script to delete keys prefixed with self.PREFIX in blocks of 5000.

Warning

This operation was designed to be fast, but was not tested on a large production based system. Be careful with its usage as it could be slow on very large data sets.

async get(key: str) int[source]
Parameters:

key – the key to get the counter value for

async get_expiry(key: str) int[source]
Parameters:

key – the key to get the expiry for

async check() bool[source]

Check if storage is healthy by calling coredis.Redis.ping() on the replica.

Async Memcached Storage

class MemcachedStorage(*args: Any, **kwargs: Any)[source]

Rate limit storage with memcached as backend.

Depends on emcache

Added in version 2.1.

Parameters:
  • uri – memcached location of the form async+memcached://host:port,host:port

  • wrap_exceptions – Whether to wrap storage exceptions in limits.errors.StorageError before raising it.

  • options – all remaining keyword arguments are passed directly to the constructor of emcache.Client

Raises:

ConfigurationError – when emcache is not available

STORAGE_SCHEME: List[str] | None = ['async+memcached']

The storage scheme for memcached to be used in an async context

DEPENDENCIES: Dict[str, Version | None] | List[str] = ['emcache']

The python modules this class has a dependency on. Used to lazily populate the dependencies

async get(key: str) int[source]
Parameters:

key – the key to get the counter value for

async clear(key: str) None[source]
Parameters:

key – the key to clear rate limits for

async incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int[source]

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • elastic_expiry – whether to keep extending the rate limit window every hit.

  • amount – the number to increment by

async get_expiry(key: str) int[source]
Parameters:

key – the key to get the expiry for

async check() bool[source]

Check if storage is healthy by calling the get command on the key limiter-check

async reset() int | None[source]

reset storage to clear limits

Async MongoDB Storage

class MongoDBStorage(*args: Any, **kwargs: Any)[source]

Rate limit storage with MongoDB as backend.

Depends on motor

Changed in version 3.14.0: Added option to select custom collection names for windows & counters

Added in version 2.1.

Parameters:
  • uri – uri of the form async+mongodb://[user:password]@host:port?..., This uri is passed directly to AsyncIOMotorClient

  • database_name – The database to use for storing the rate limit collections.

  • counter_collection_name – The collection name to use for individual counters used in fixed window strategies

  • window_collection_name – The collection name to use for moving window storage

  • wrap_exceptions – Whether to wrap storage exceptions in limits.errors.StorageError before raising it.

  • options – all remaining keyword arguments are passed to the constructor of AsyncIOMotorClient

Raises:

ConfigurationError – when the motor or pymongo are not available

STORAGE_SCHEME: List[str] | None = ['async+mongodb', 'async+mongodb+srv']

The storage scheme for MongoDB for use in an async context

DEPENDENCIES: Dict[str, Version | None] | List[str] = ['motor.motor_asyncio', 'pymongo']

The python modules this class has a dependency on. Used to lazily populate the dependencies

async reset() int | None[source]

Delete all rate limit keys in the rate limit collections (counters, windows)

async clear(key: str) None[source]
Parameters:

key – the key to clear rate limits for

async get_expiry(key: str) int[source]
Parameters:

key – the key to get the expiry for

async get(key: str) int[source]
Parameters:

key – the key to get the counter value for

async incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int[source]

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • elastic_expiry – whether to keep extending the rate limit window every hit.

  • amount – the number to increment by

async check() bool[source]

Check if storage is healthy by calling motor.motor_asyncio.AsyncIOMotorClient.server_info()

async get_moving_window(key: str, limit: int, expiry: int) Tuple[int, int][source]

returns the starting point and the number of entries in the moving window

Parameters:
  • key (str) – rate limit key

  • expiry (int) – expiry of entry

Returns:

(start of window, number of acquired entries)

async acquire_entry(key: str, limit: int, expiry: int, amount: int = 1) bool[source]
Parameters:
  • key – rate limit key to acquire an entry in

  • limit – amount of entries allowed

  • expiry – expiry of the entry

  • amount – the number of entries to acquire

Async Etcd Storage

class EtcdStorage(*args: Any, **kwargs: Any)[source]

Rate limit storage with etcd as backend.

Depends on aetcd.

Parameters:
  • uri – etcd location of the form async+etcd://host:port,

  • max_retries – Maximum number of attempts to retry in the case of concurrent updates to a rate limit key

  • options – all remaining keyword arguments are passed directly to the constructor of aetcd.client.Client

Raises:

ConfigurationError – when aetcd is not available

STORAGE_SCHEME: List[str] | None = ['async+etcd']

The async storage scheme for etcd

DEPENDENCIES: Dict[str, Version | None] | List[str] = ['aetcd']

The python modules this class has a dependency on. Used to lazily populate the dependencies

async incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int[source]

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • elastic_expiry – whether to keep extending the rate limit window every hit.

  • amount – the number to increment by

async get(key: str) int[source]
Parameters:

key – the key to get the counter value for

async get_expiry(key: str) int[source]
Parameters:

key – the key to get the expiry for

async check() bool[source]

check if storage is healthy

async reset() int | None[source]

reset storage to clear limits

async clear(key: str) None[source]

resets the rate limit key

Parameters:

key – the key to clear rate limits for

Abstract storage classes

class Storage(*args: Any, **kwargs: Any)[source]

Base class to extend when implementing a storage backend.

Parameters:

wrap_exceptions – Whether to wrap storage exceptions in limits.errors.StorageError before raising it.

STORAGE_SCHEME: List[str] | None

The storage schemes to register against this implementation

abstract incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int[source]

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • elastic_expiry – whether to keep extending the rate limit window every hit.

  • amount – the number to increment by

abstract get(key: str) int[source]
Parameters:

key – the key to get the counter value for

abstract get_expiry(key: str) int[source]
Parameters:

key – the key to get the expiry for

abstract check() bool[source]

check if storage is healthy

abstract reset() int | None[source]

reset storage to clear limits

abstract clear(key: str) None[source]

resets the rate limit key

Parameters:

key – the key to clear rate limits for

DEPENDENCIES: Dict[str, Version | None] | List[str] = []

The python modules this class has a dependency on. Used to lazily populate the dependencies

class MovingWindowSupport(*args: Any, **kwargs: Any)[source]

Abstract base for storages that intend to support the moving window strategy

abstract acquire_entry(key: str, limit: int, expiry: int, amount: int = 1) bool[source]
Parameters:
  • key – rate limit key to acquire an entry in

  • limit – amount of entries allowed

  • expiry – expiry of the entry

  • amount – the number of entries to acquire

abstract get_moving_window(key: str, limit: int, expiry: int) Tuple[int, int][source]

returns the starting point and the number of entries in the moving window

Parameters:
  • key – rate limit key

  • expiry – expiry of entry

Returns:

(start of window, number of acquired entries)

Async variants

class Storage(*args: Any, **kwargs: Any)[source]

Base class to extend when implementing an async storage backend.

Added in version 2.1.

Parameters:

wrap_exceptions – Whether to wrap storage exceptions in limits.errors.StorageError before raising it.

STORAGE_SCHEME: List[str] | None

The storage schemes to register against this implementation

abstract async incr(key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1) int[source]

increments the counter for a given rate limit key

Parameters:
  • key – the key to increment

  • expiry – amount in seconds for the key to expire in

  • elastic_expiry – whether to keep extending the rate limit window every hit.

  • amount – the number to increment by

abstract async get(key: str) int[source]
Parameters:

key – the key to get the counter value for

abstract async get_expiry(key: str) int[source]
Parameters:

key – the key to get the expiry for

abstract async check() bool[source]

check if storage is healthy

abstract async reset() int | None[source]

reset storage to clear limits

abstract async clear(key: str) None[source]

resets the rate limit key

Parameters:

key – the key to clear rate limits for

DEPENDENCIES: Dict[str, Version | None] | List[str] = []

The python modules this class has a dependency on. Used to lazily populate the dependencies

class MovingWindowSupport(*args: Any, **kwargs: Any)[source]

Abstract base for storages that intend to support the moving window strategy

abstract async acquire_entry(key: str, limit: int, expiry: int, amount: int = 1) bool[source]
Parameters:
  • key – rate limit key to acquire an entry in

  • limit – amount of entries allowed

  • expiry – expiry of the entry

  • amount – the number of entries to acquire

abstract async get_moving_window(key: str, limit: int, expiry: int) Tuple[int, int][source]

returns the starting point and the number of entries in the moving window

Parameters:
  • key – rate limit key

  • expiry – expiry of entry

Returns:

(start of window, number of acquired entries)

Rate Limits

Provided by limits

Parsing functions

parse(limit_string: str) RateLimitItem[source]

parses a single rate limit in string notation (e.g. 1/second or 1 per second)

Parameters:

limit_string – rate limit string using Rate limit string notation

Raises:

ValueError – if the string notation is invalid.

parse_many(limit_string: str) List[RateLimitItem][source]

parses rate limits in string notation containing multiple rate limits (e.g. 1/second; 5/minute)

Parameters:

limit_string – rate limit string using Rate limit string notation

Raises:

ValueError – if the string notation is invalid.

Rate limit granularities

All rate limit items implement RateLimitItem by declaring a GRANULARITY

class RateLimitItem(amount: int, multiples: int | None = 1, namespace: str = 'LIMITER')[source]

defines a Rate limited resource which contains the characteristic namespace, amount and granularity multiples of the rate limiting window.

Parameters:
  • amount – the rate limit amount

  • multiples – multiple of the ‘per’ GRANULARITY (e.g. ‘n’ per ‘m’ seconds)

  • namespace – category for the specific rate limit

GRANULARITY: ClassVar[Granularity]

A tuple describing the granularity of this limit as (number of seconds, name)

classmethod check_granularity_string(granularity_string: str) bool[source]

Checks if this instance matches a granularity_string of type n per hour, n per minute etc, by comparing with GRANULARITY

get_expiry() int[source]
Returns:

the duration the limit is enforced for in seconds.

key_for(*identifiers: str) str[source]

Constructs a key for the current limit and any additional identifiers provided.

Parameters:

identifiers – a list of strings to append to the key

Returns:

a string key identifying this resource with each identifier appended with a ‘/’ delimiter.


class RateLimitItemPerSecond(amount: int, multiples: int | None = 1, namespace: str = 'LIMITER')[source]

per second rate limited resource.

classmethod check_granularity_string(granularity_string: str) bool

Checks if this instance matches a granularity_string of type n per hour, n per minute etc, by comparing with GRANULARITY

get_expiry() int
Returns:

the duration the limit is enforced for in seconds.

key_for(*identifiers: str) str

Constructs a key for the current limit and any additional identifiers provided.

Parameters:

identifiers – a list of strings to append to the key

Returns:

a string key identifying this resource with each identifier appended with a ‘/’ delimiter.

GRANULARITY: ClassVar[Granularity] = (1, 'second')

A second

class RateLimitItemPerMinute(amount: int, multiples: int | None = 1, namespace: str = 'LIMITER')[source]

per minute rate limited resource.

classmethod check_granularity_string(granularity_string: str) bool

Checks if this instance matches a granularity_string of type n per hour, n per minute etc, by comparing with GRANULARITY

get_expiry() int
Returns:

the duration the limit is enforced for in seconds.

key_for(*identifiers: str) str

Constructs a key for the current limit and any additional identifiers provided.

Parameters:

identifiers – a list of strings to append to the key

Returns:

a string key identifying this resource with each identifier appended with a ‘/’ delimiter.

GRANULARITY: ClassVar[Granularity] = (60, 'minute')

A minute

class RateLimitItemPerHour(amount: int, multiples: int | None = 1, namespace: str = 'LIMITER')[source]

per hour rate limited resource.

GRANULARITY: ClassVar[Granularity] = (3600, 'hour')

An hour

classmethod check_granularity_string(granularity_string: str) bool

Checks if this instance matches a granularity_string of type n per hour, n per minute etc, by comparing with GRANULARITY

get_expiry() int
Returns:

the duration the limit is enforced for in seconds.

key_for(*identifiers: str) str

Constructs a key for the current limit and any additional identifiers provided.

Parameters:

identifiers – a list of strings to append to the key

Returns:

a string key identifying this resource with each identifier appended with a ‘/’ delimiter.

class RateLimitItemPerDay(amount: int, multiples: int | None = 1, namespace: str = 'LIMITER')[source]

per day rate limited resource.

GRANULARITY: ClassVar[Granularity] = (86400, 'day')

A day

classmethod check_granularity_string(granularity_string: str) bool

Checks if this instance matches a granularity_string of type n per hour, n per minute etc, by comparing with GRANULARITY

get_expiry() int
Returns:

the duration the limit is enforced for in seconds.

key_for(*identifiers: str) str

Constructs a key for the current limit and any additional identifiers provided.

Parameters:

identifiers – a list of strings to append to the key

Returns:

a string key identifying this resource with each identifier appended with a ‘/’ delimiter.

class RateLimitItemPerMonth(amount: int, multiples: int | None = 1, namespace: str = 'LIMITER')[source]

per month rate limited resource.

GRANULARITY: ClassVar[Granularity] = (2592000, 'month')

A month

classmethod check_granularity_string(granularity_string: str) bool

Checks if this instance matches a granularity_string of type n per hour, n per minute etc, by comparing with GRANULARITY

get_expiry() int
Returns:

the duration the limit is enforced for in seconds.

key_for(*identifiers: str) str

Constructs a key for the current limit and any additional identifiers provided.

Parameters:

identifiers – a list of strings to append to the key

Returns:

a string key identifying this resource with each identifier appended with a ‘/’ delimiter.

class RateLimitItemPerYear(amount: int, multiples: int | None = 1, namespace: str = 'LIMITER')[source]

per year rate limited resource.

GRANULARITY: ClassVar[Granularity] = (31104000, 'year')

A year

classmethod check_granularity_string(granularity_string: str) bool

Checks if this instance matches a granularity_string of type n per hour, n per minute etc, by comparing with GRANULARITY

get_expiry() int
Returns:

the duration the limit is enforced for in seconds.

key_for(*identifiers: str) str

Constructs a key for the current limit and any additional identifiers provided.

Parameters:

identifiers – a list of strings to append to the key

Returns:

a string key identifying this resource with each identifier appended with a ‘/’ delimiter.

Structures

class WindowStats(reset_time: int, remaining: int)[source]

Tuple to describe a rate limited window

Create new instance of WindowStats(reset_time, remaining)

reset_time: int

Time as seconds since the Epoch when this window will be reset

remaining: int

Quantity remaining in this window

Exceptions

exception ConfigurationError[source]

Error raised when a configuration problem is encountered

exception ConcurrentUpdateError(key: str, attempts: int)[source]

Error raised when an update to limit fails due to concurrent updates

exception StorageError(storage_error: Exception)[source]

Error raised when an error is encountered in a storage