Asynchronous task queue and scheduler for Python, where one task runs on exactly one worker.
🚀 Project
Queuefy is a task queue and a scheduler that are the same thing.
Everything it does reduces to a single row: a run that is due, which exactly one worker claims. An immediate task, an interval, a fixed datetime and a cron expression differ only in when the next run is written, and in nothing else.
That is why there is no separate scheduler process, no broker and no leader election. Start it on ten machines and the nightly report still runs once.
✨ Features
- Run a task now, off the request that asked for it
- Run a task every N seconds
- Run a task once, at a stated date and time
- Run a task on a cron expression
- One run on exactly one worker, however many processes, workers and machines
- Retries with fixed, linear, exponential and jittered policies
- Timeouts, heartbeats and recovery of what a dead worker was holding
- Named queues and priorities
- Lifecycle hooks for auditing, metrics and alerting
- Pluggable stores: PostgreSQL 14+, MySQL 8.0+, Redis 7+, SQLite and memory
- Survives a kill: what a dead worker held comes back, and a schedule resumes where it stopped
- No dependencies in the core
- 100% branch coverage: one contract against every store, plus multi-worker, multi-machine, everyday, disaster and interrupted-call suites
📦 Install
pip install "queuefy[sqlalchemy]"
Or with Redis:
pip install "queuefy[redis]"
🧭 The four ways to ask for work
| What you want | How you ask for it |
|---|---|
| run it now | await app.enqueue("send_email", to="a@b.com") |
| run it every 30 seconds | @app.task("poll", every=30) |
| run it once, at a stated time | await app.enqueue_at("report", when) |
| run it on a cron expression | @app.task("nightly", cron="0 4 * * *") |
💡 How to use
import asyncio
from sqlalchemy.ext.asyncio import create_async_engine
from queuefy.app import Queuefy
from queuefy.store.sqlalchemy import SqlAlchemyStore
from queuefy.worker import Worker
app = Queuefy(SqlAlchemyStore(create_async_engine("sqlite+aiosqlite:///app.db")))
@app.task("send_email", max_attempts=5, timeout=30)
async def send_email(to: str, subject: str):
...
@app.task("nightly_report", cron="0 4 * * *")
async def nightly_report():
...
async def main():
await app.setup()
await app.enqueue("send_email", to="reader@example.com", subject="Welcome")
await Worker(app, concurrency=8).run()
asyncio.run(main())
🧱 The words it uses
Three of them, and each means one thing:
| Word | What it is |
|---|---|
| Task | what you declare: a name, the code, and the policy it runs under |
| Run | one execution of a task, which is the only thing a worker ever claims |
| Queue | a named lane a task belongs to, and a worker serves |
📚 Documentation
- Getting started
- Tasks — the four kinds, and what a name means
- Workers — concurrency, leases and many machines
- Retries and failures — policies, timeouts, permanent errors
- Hooks — being told about every run
- Stores — SQLAlchemy, Redis, memory, and writing your own
- Frameworks — the rule that covers all of them, and what a handler may touch
- Contribution — how to help
☕ Buy me a coffee
Support the continuous development of this project.
📄 License
Copyright (c) 2026, Paulo Coutinho
Metadata
Release files for queuefy 1.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| queuefy-1.0.3.tar.gz | 233.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| queuefy-1.0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 282.7 kB
Release files / queuefy-1.0.3.tar.gz
| Download URL | queuefy-1.0.3.tar.gz |
|---|---|
| Size | 233.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d40b7204057df550ea7ad7c1ac18774918836b063325ee879368c2f031124561
|
|
BLAKE2b-256 checksum How to use checksums |
883419a713762cd0537fc4d083f3e36b090c5aacfd8cdd48f7f28c1fc2dc5fb3
|
| 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 Aug 14, 2026.
Transparency logRelease files / queuefy-1.0.3-py3-none-any.whl
| Download URL | queuefy-1.0.3-py3-none-any.whl |
|---|---|
| Size | 48.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1b64ec9cf2594ad03b5d70411cd1b6bd73de1579bd988296034c26437767a07b
|
|
BLAKE2b-256 checksum How to use checksums |
b852d740374ad4160989ad4fba51c83df50c1eb64563c13e1eed09757e1722b0
|
| 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 Aug 14, 2026.
Transparency log