Skip to main content

Developers Toolbox

Leaky Bucket

Rate-limit events with a leaky bucket. Arrivals that fit are admitted. In drop mode the rest are rejected. In queue mode they wait until leaked capacity can take them.

The PyPI name is lupaxa-leaky-bucket. The import path is lupaxa.leaky_bucket. lupaxa is a namespace package — there is no lupaxa/__init__.py.

Install

pip install lupaxa-leaky-bucket

Requires Python 3.10+. There are no runtime dependencies.

From a clone of this repository (editable install):

make init
make python-install-dev

Usage

lupaxa-leaky-bucket is a library only. There is no console script and no python -m entry point.

from lupaxa.leaky_bucket import LeakyBucket

bucket = LeakyBucket(capacity=5, leak_rate=5, mode="drop")

if bucket.allow():
    handle_request()

Units are whatever you count: requests, jobs, or bytes. capacity is the burst limit. leak_rate is how many units leak per second. Set both when you construct the bucket. Each must be finite and greater than zero.

Parameter Default Meaning
capacity required Burst limit, in your units
leak_rate required Units leaked per second
time_provider SystemTimeProvider Clock with now() -> float
mode "drop" "drop" or "queue"
raise_on_overflow False In drop mode, raise BucketOverflow instead of False
drain_on_shutdown False shutdown() waits until the bucket and queue are empty

mode must be "drop" or "queue". Anything else raises InvalidBucketMode. raise_on_overflow=True is valid only in drop mode. Queue mode with that flag raises LeakyBucketError.

Admitting work

allow(amount=1.0) leaks for the time since the last check, then tries to add amount as a whole. It does not take part of an amount. amount must be finite and greater than zero. A bad amount raises LeakyBucketError.

Situation Drop mode Queue mode
Amount fits now Add it and return True Add it and return True
Amount fits later, not now Return False, or raise BucketOverflow Append it and return True
Amount is larger than capacity Return False, or raise BucketOverflow Raise BucketOverflow

An amount larger than capacity can never be admitted. Queue mode raises rather than parking it, because that arrival would block everything behind it. Drop mode raises only when raise_on_overflow is set.

Queue mode returns True for an amount that is waiting. The caller has handed the bucket the work. pending_count() and has_pending() report what is still waiting. Both leak before they answer, so a queued amount that now fits is admitted by the read.

Inspecting the bucket

Every read leaks first, using the same clock as allow().

Method Returns
current_level() Water currently in the bucket
remaining_capacity() capacity - level, never below zero
pending_count() How many queued amounts are still waiting
has_pending() Whether the queue is non-empty
fill_ratio() Fullness from 0.0 to 1.0
fill_percent() Fullness from 0 to 100
peek() One snapshot of level, remaining, pending, and fill

peek() leaks once and builds every field from that moment:

bucket.peek()
# {
#     "level": 1.0,
#     "remaining": 4.0,
#     "pending": 0,
#     "fill_ratio": 0.2,
#     "fill_percent": 20.0,
# }

level, remaining, and fill_ratio are rounded for display. fill_percent is rounded to one decimal place. The bucket keeps full precision for later leaks.

Shutdown

bucket = LeakyBucket(capacity=5, leak_rate=1, mode="queue", drain_on_shutdown=True)
bucket.allow()
bucket.shutdown()

shutdown() with drain_on_shutdown=False sets the level to zero and clears the queue. With drain_on_shutdown=True the clock advances by the time needed to admit each queued amount, then by the time needed to empty the bucket. An advanceable clock is stepped directly. The system clock sleeps.

Clock

SystemTimeProvider uses time.monotonic(). A wall-clock step does not refill the bucket. A custom provider only needs now() -> float. If that clock moves backwards, elapsed time is ignored until it catches up, so the level does not grow.

AdvanceableTimeProvider is the protocol for a test or demo clock that also implements advance(seconds). shutdown() calls advance when the provider matches that protocol.

Threads

Public methods share one lock. Several threads may call allow() and the read methods on the same bucket. shutdown() keeps that lock while it drains, so other callers wait until the drain finishes.

Errors and version

Name When
LeakyBucketError Base error: bad capacity, leak rate, amount, or conflicting flags
BucketOverflow An arrival does not fit and the call is configured to raise
InvalidBucketMode mode is not "drop" or "queue"
__version__ Package version string
get_version() Same string as __version__

BucketOverflow and InvalidBucketMode are subclasses of LeakyBucketError.

Demos

Scripts under demo/ are examples. They are not part of the wheel. Install the package first (make python-install-dev), then run them from the repository root.

python demo/demo_live.py --queue --capacity 5 --rate 1 --events 10
python demo/demo_timeline.py
python demo/demo_worker.py --jobs 20 --rate 1 --capacity 5
python demo/demo_copy.py input.txt output.txt --rate 100000
Script What it shows
demo_live.py Flags on the real clock: mode, capacity, rate, interval, and drain
demo_timeline.py Drop, queue, and drain on a fake clock, printed back to back with no sleeping
demo_worker.py A fast producer and a worker that waits in drop mode until each job fits
demo_copy.py A file copy charged in bytes per chunk

demo_copy.py refuses a chunk larger than the rate. One read has to fit in the bucket. demo_worker.py keeps jobs on a normal queue. The bucket only decides when the worker may take the next job. The main thread waits until that worker, including shutdown(), has finished.

Check

make init
make python-check
The Lupaxa Project Footer

Metadata

Release files for lupaxa-leaky-bucket 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 lupaxa-leaky-bucket 0.1.0
File Size Uploaded
lupaxa_leaky_bucket-0.1.0.tar.gz 8.1 kB Details

Built distribution (wheel)

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

Total release size: 18.1 kB

Release files / lupaxa_leaky_bucket-0.1.0.tar.gz

Download URL lupaxa_leaky_bucket-0.1.0.tar.gz
Size 8.1 kB
Tags Source
SHA-256 checksum
How to use checksums
e6c752e7cd56a734cdd7b94e686e14e92e810a726cd971539a1da34a1b085d6a
BLAKE2b-256 checksum
How to use checksums
6861c59846c1f442ccc5028e52f73e3121ec772cfa9327c1ed2d7d66ea82cf1d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.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 Sep 30, 2026.

Transparency log

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

Download URL lupaxa_leaky_bucket-0.1.0-py3-none-any.whl
Size 9.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
abb60dfb5dd61c60d9004e8a8595d11676a27a8aaff4c76c73a887cd2b2ab93f
BLAKE2b-256 checksum
How to use checksums
40f0e6c0615da81ba95a297ec457d44881370fdad523a8fd7555baa3421ad355
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.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 Sep 30, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.1

2 release files

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