Small rate limiters for when you do not want Redis: a token bucket and a sliding window, both dependency-free and thread-safe.
from ratelimit_kit import TokenBucket
bucket = TokenBucket(rate=5, capacity=10) # 5/s sustained, bursts up to 10
if bucket.consume():
send_request()
else:
sleep(bucket.time_until())Token bucket — when bursts are fine as long as the average holds. Most HTTP APIs work like this: you may fire ten requests at once, but not sustain ten per second.
Sliding window — when the limit is a hard "no more than N per minute" and a burst at the boundary would be a violation. A fixed window lets 2x through around the edge; this one does not.
from ratelimit_kit import limit, alimit
@limit(rate=5) # blocks until a token is free
def fetch(url): ...
@alimit(rate=5) # awaits, keeps the event loop free
async def afetch(url): ...Both limiters take a clock argument, so tests do not have to sleep:
class FakeClock:
def __init__(self): self.now = 0.0
def __call__(self): return self.now
def advance(self, s): self.now += s
clock = FakeClock()
bucket = TokenBucket(rate=1, capacity=1, clock=clock)
bucket.consume()
clock.advance(1)
assert bucket.consume()pip install ratelimit-kitPython 3.9+, no dependencies.
MIT