A lightweight, decorator-based rate limiter for Python applications.
rateflow protects synchronous functions, asynchronous functions, Flask routes,
and FastAPI endpoints with four algorithms:
- Fixed window
- Sliding window
- Token bucket
- Leaky bucket
It supports process-local in-memory state and Redis-backed shared state.
Requirements
- Python 3.10 or newer
- Redis 6 or newer when using Redis storage
The current package release includes the Redis, Flask, FastAPI, Uvicorn, and pytest dependencies declared in the project metadata.
Installation
python -m pip install rateflow
Quick start
Configure a storage backend before defining decorated functions:
from rateflow import Algorithm, Configure, Storage, rate_limit
from rateflow.exceptions import RateLimitExceed
Configure.configure(Storage.MEMORY)
@rate_limit({
"algorithm": Algorithm.FIXED_WINDOW,
"calls": 5,
"period": 60,
})
def get_data():
return {"status": "ok"}
try:
get_data()
except RateLimitExceed:
print("rate limit exceeded")
The limiter consumes a permit before calling the wrapped function. A failed wrapped function still consumes the permit.
Configuration
The algorithm field is required. Required fields depend on the algorithm:
| Algorithm | Required fields | Description |
|---|---|---|
Algorithm.FIXED_WINDOW |
calls, period |
Allows a fixed number of calls during each period. |
Algorithm.SLIDING_WINDOW |
calls, period |
Tracks permitted request timestamps over a rolling period. |
Algorithm.TOKEN_BUCKET |
capacity, refill_rate |
Consumes tokens and replenishes them continuously. |
Algorithm.LEAKY_BUCKET |
capacity, leak_rate |
Accepts requests while the bucket has capacity and drains continuously. |
Invalid or incomplete configuration raises ValueError. The legacy
refill_bucket field is accepted as an alias for refill_rate.
Token bucket
@rate_limit({
"algorithm": Algorithm.TOKEN_BUCKET,
"capacity": 20,
"refill_rate": 2, # tokens per second
})
def send_request():
return {"status": "sent"}
Token buckets start full, refill continuously, and consume one token per permitted request.
Keys and shared limits
By default, each decorated function uses its qualified name as its storage key. A custom key can be supplied in the configuration or with the decorator's keyword argument:
@rate_limit(
{"algorithm": Algorithm.FIXED_WINDOW, "calls": 10, "period": 60},
key="api:search",
)
def search(query: str):
return query
When both key forms are provided, the decorator argument takes precedence. Functions using the same key share rate-limit state, so keys should be stable and unique within the selected storage backend.
Storage backends
In-memory
Use in-memory storage for tests, local development, or a single-process application:
Configure.configure(Storage.MEMORY)
State is process-local and is lost when the process exits. If no backend is configured, the first decorator currently selects in-memory storage automatically; explicit configuration is recommended.
Redis
Use Redis when state must be shared between workers, containers, or hosts:
Configure.configure(
Storage.REDIS,
{
"url": "redis://localhost:6379/0",
"ttl": 3600,
"socket_connect_timeout": 5,
},
)
Redis must be running before application startup. Stored keys use a configurable TTL. Redis acquisition uses an optimistic transaction, but applications should still test their required concurrency guarantees under production load.
Async usage
The decorator supports coroutine functions and checks the limit before awaiting the endpoint:
from rateflow import Algorithm, Configure, Storage, rate_limit
Configure.configure(Storage.MEMORY)
@rate_limit({
"algorithm": Algorithm.SLIDING_WINDOW,
"calls": 10,
"period": 60,
})
async def async_endpoint():
return {"status": "ok"}
With Redis storage, the current check uses synchronous Redis I/O and may block the event loop during network or Redis delays.
Framework usage
The decorator can be applied to Flask and FastAPI endpoints in the same way as ordinary functions:
@app.get("/items")
@rate_limit({"algorithm": Algorithm.FIXED_WINDOW, "calls": 10, "period": 60})
def items():
return {"status": "ok"}
Errors
ValueErroris raised for missing or invalid rate-limit configuration.RateLimitExceedis raised when a permitted request would exceed its limit.
License
MIT License: LICENSE
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rateflow-1.0.1.tar.gz.
File metadata
- Download URL: rateflow-1.0.1.tar.gz
- Upload date:
- Size: 17.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f2f4346cb0fa6450bbc184585a7c92b52668721fdbfa0ddf6b8ee74d88c8ccd4
|
|
| MD5 |
abf2796a8aa5b73631bca4e2112f7bd9
|
|
| BLAKE2b-256 |
552c076ccc48cf90af9f4986a6ec1b55ac6a8403bd1ecd8f87ee87d9e350a31c
|
File details
Details for the file rateflow-1.0.1-py3-none-any.whl.
File metadata
- Download URL: rateflow-1.0.1-py3-none-any.whl
- Upload date:
- Size: 20.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6b7d43c2c5c1c868fbc708d9d2a0f55e370229707db60754e73b05040293bbbf
|
|
| MD5 |
92049c7a28eec4f1919f4eb9a75e1435
|
|
| BLAKE2b-256 |
b7bf1852be9c89a0057d64205930fef19e9ae88d836413b242a9e5183f7e1a0b
|