Skip to main content

throttlepy

Token bucket and sliding window rate limiting for Python. In-memory or Redis-backed. Sync and async.

CI Python License: MIT

Install

pip install throttlepy               # in-memory only
pip install throttlepy[redis]        # + distributed Redis backend

Quickstart

from throttlepy import Limiter, MemoryStorage, TokenBucket

limiter = Limiter(
    algorithm=TokenBucket(capacity=10, refill_per_sec=1.0),
    storage=MemoryStorage(),
)

if limiter.try_acquire("user:42"):
    ...  # do the thing

Two algorithms. Two storages. Two API styles (sync + async). Three ergonomics (try_acquire, acquire+exception, with throttle():).

Algorithms

Algorithm When to use
TokenBucket(capacity, refill_per_sec) Bursts are fine; smooth long-term rate
SlidingWindow(limit, window_sec) Strict limit-per-window (billing, quotas)

See docs/algorithms.md for the trade-offs.

Async

from throttlepy import AsyncLimiter, AsyncMemoryStorage, TokenBucket

limiter = AsyncLimiter(
    algorithm=TokenBucket(capacity=10, refill_per_sec=1.0),
    storage=AsyncMemoryStorage(),
)

async with limiter.throttle("user:42"):
    ...

Distributed (Redis)

from redis import Redis
from throttlepy import Limiter, TokenBucket
from throttlepy.storage.redis import RedisStorage

limiter = Limiter(
    algorithm=TokenBucket(capacity=100, refill_per_sec=10.0),
    storage=RedisStorage(Redis(host="localhost")),
)

Redis backend uses atomic Lua scripts for both algorithms — safe under concurrent multi-process load.

Decorator

from throttlepy import Limiter, MemoryStorage, TokenBucket, rate_limit

limiter = Limiter(TokenBucket(capacity=5, refill_per_sec=1.0), MemoryStorage())

@rate_limit(limiter, key=lambda user_id: f"user:{user_id}")
def make_request(user_id: str) -> None:
    ...  # RateLimitExceeded is raised if over limit

Works on async functions too (pass an AsyncLimiter).

Testing your own code

Inject a Clock implementation to control time in tests:

class FakeClock:
    def __init__(self, t: float = 0.0) -> None: self.t = t
    def now(self) -> float: return self.t
    def advance(self, seconds: float) -> None: self.t += seconds

limiter = Limiter(TokenBucket(1, 1.0), MemoryStorage(), clock=FakeClock())

Examples

Benchmarks

just bench

Runs benchmarks/bench.py against MemoryStorage. Report numbers from your own machine — don't quote mine.

Contributing

just setup    # install deps into .venv
just test     # run pytest
just lint     # ruff + mypy
just format   # apply fixes

License

MIT

Metadata

Release files for throttlepy 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for throttlepy 0.1.0
File Size Uploaded
throttlepy-0.1.0.tar.gz 36.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for throttlepy 0.1.0
File Interpreter ABI Platform
throttlepy-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 46.1 kB

Release files / throttlepy-0.1.0.tar.gz

Download URL throttlepy-0.1.0.tar.gz
Size 36.6 kB
Tags Source
SHA-256 checksum
How to use checksums
20cdd876dc7fe92729a7c24366bf0034da023046cf85ac18feee4ab450fd2212
BLAKE2b-256 checksum
How to use checksums
1865691fa3ef4e928c76d5745a68ba0ae18aecdc267254e24109db700f174e5e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 20, 2026.

Transparency log

Release files / throttlepy-0.1.0-py3-none-any.whl

Download URL throttlepy-0.1.0-py3-none-any.whl
Size 9.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0691012c3d7b000748ca32441d9aac0152697a6871cc7f22294463f9fb73a732
BLAKE2b-256 checksum
How to use checksums
ff4ad7e7dbad5b400138d3d3c33a27760ccb40c2a650bbd5b0db01c340eccb40
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 20, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page