Compare pgtask¶
Choose the storage model before you compare task decorators.
pgtask keeps task state in PostgreSQL. You can enqueue work in the same transaction as your application data:
async with connection.transaction():
await connection.execute(
"INSERT INTO reports (id, status) VALUES (%s, %s)",
(report_id, "pending"),
)
await Client.enqueue_on(
connection,
render.request(
{"report_id": report_id},
idempotency_key=f"report:{report_id}",
),
)
If the transaction rolls back, neither write exists. This is the main reason to choose pgtask over a broker-backed
queue.
Choose by constraint¶
| Choose | When you need |
|---|---|
pgtask |
Transactional enqueue, PostgreSQL as the only state store, or durable functions |
| Absurd | Durable functions with the smallest PostgreSQL-native footprint |
| Celery | A mature Python ecosystem, several broker choices, or Canvas workflows |
| Dramatiq | A small, fast Python task queue backed by RabbitMQ or Redis |
| ARQ | A compact async Python queue when Redis is already part of your stack |
There is no universal winner. Celery has a much larger ecosystem. Dramatiq is faster in the repository's local
no-operation benchmark. Absurd has a smaller engine. ARQ has less surface area. pgtask chooses database consistency
and durable execution over all four.
Compare guarantees¶
| Question | pgtask |
Broker-backed queues | Absurd |
|---|---|---|---|
| Where does pending work live? | PostgreSQL | A broker such as Redis or RabbitMQ | PostgreSQL |
| Can enqueue join your application transaction? | Yes | Not without an outbox | Yes, when you use the same database transaction |
| Can a function sleep and resume after a restart? | Yes | Compose another task or add application state | Yes |
| What must you operate? | PostgreSQL and workers | A broker, workers, and sometimes a result backend or scheduler | PostgreSQL and workers |
Compare the failure model before the feature list. A fast enqueue that can disagree with your application row is not equivalent to a committed database task. A durable step that replays after a crash is not equivalent to a chain of messages.
Compare performance with your workload¶
The repository includes a local comparison against Celery and Dramatiq. It measures trivial tasks on one laptop. It is useful for finding overhead. It is not a production capacity claim.
Run the same test with your handler duration, payload size, database latency, broker durability, and worker shape. Those choices move the result more than the library name.
Migrate after you choose¶
Each comparison ends with a migration section when the systems have a safe cutover path. The migration comes last because syntax is the easy part. Storage, delivery, scheduling, and workflow guarantees decide whether you should move at all.