dbworker
Your database rows are already the queue.
A portable, single-script background worker for SQLAlchemy. No broker, no enqueue, no duplicate job model.
Celery / Huey / Graphile Worker:
event → job → worker
dbworker:
row → worker
Requires Python 3.12+. Install into your application:
poetry add dbworker
Usage
Register a handler for an existing SQLAlchemy model. DBWorker discovers eligible rows, runs the handler in a child process, and commits its database changes with the execution status.
from sqlalchemy import select
from sqlalchemy.orm import Session
from dbworker import Coordinator, Finished
coordinator = Coordinator(session_factory, database_url=database_url)
@coordinator.transactional_worker(
name="process",
source=YourModel,
eligible=lambda: (
select(YourModel)
.where(YourModel.your_bool_property.is_(True))
.order_by(YourModel.id)
),
concurrency=4,
)
def process(source: YourModel, session: Session) -> Finished:
# Apply your application logic using the supplied session.
return Finished()
if __name__ == "__main__":
coordinator.create_worker_tables()
coordinator.start()
YourModel, session_factory, and database_url come from your application.
eligible selects which rows can be claimed and in what order.
It is optional: omitting it selects from the whole model. DBWorker automatically
excludes completed, failed, and actively claimed work.
Return Finished() when processing is complete; no enqueue call is needed.
See the Usage Instructions for eligibility queries, incremental processing, service startup and shutdown, status tracking, dependencies, failure handling, and configuration.
Examples
- Image deduplication: independent FastAPI and worker services, artifact building, paged comparisons, and worker dependencies.
- Redis + Celery equivalent.
- Benchmarks with structured JSON results.
License
MIT © 2026 Ziyang Song.
Benchmark Results
Median wall time in seconds; bold marks the faster backend. Each experiment runs in a fresh Docker container on its own GitHub-hosted Ubuntu VM. Fixed profile: 8 producers, a 60-second scheduled submission window and 8 total execution slots; image hash building uses one native bulk import. Three repetitions per backend. Actual schedule delays and backlog are recorded in JSON; this is one load point, not a maximum-capacity search.
| Experiment | Workload | Celery wall (s) | DBWorker wall (s) | C / D | Task P95 / peak outstanding (C; D) |
|---|---|---|---|---|---|
| imagededup | Build 1,000 image hashes (one bulk import) | 5.760 | 7.068 | 0.81 | n/a; n/a |
| imagededup | Compare 1,000 images / 999,000 directed pairs | 79.744 | 75.987 | 1.05 | n/a; n/a |
| imagededup | Build + compare 1,000 images / 999,000 directed pairs | 90.392 | 90.100 | 1.00 | n/a; n/a |
| superset | SQL Lab: 3,000 queries / 10,000 rows | 146.495 | 166.948 | 0.88 | 41.240s / 1510; 47.638s / 1477 |
| saleor | Export: 1,000 x 256 products + 1,000 emails | 130.202 | 165.889 | 0.78 | 36.031s / 604; 56.666s / 885 |
| paperless_ngx | OCR: 200 scans, archive and index | 126.469 | 71.819 | 1.76 | 63.548s / 108; 44.893s / 41 |
| posthog | 2FA: 5,000 requests / 10,000 tasks | 118.121 | 147.444 | 0.80 | 0.113s / 15; 36.036s / 2268 |
| sentry | Email: 2,000 requests / 4,000 deliveries | 60.306 | 60.418 | 1.00 | 0.052s / 16; 0.517s / 161 |
Run: github-38165895322-1. Details and scope · JSON results.
Scoped application workloads; Sentry uses historical 24.1.0. Wall time includes the fixed submission window, so a ratio near 1 does not prove equal processing capacity. Task P95 starts at publication; peak outstanding counts already published tasks. Ratios above 1 favor DBWorker; no cross-project average is computed.
Metadata
Release files for dbworker 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dbworker-0.1.1.tar.gz | 33.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dbworker-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 44.1 kB
Release files / dbworker-0.1.1.tar.gz
| Download URL | dbworker-0.1.1.tar.gz |
|---|---|
| Size | 33.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ef76d7e11aa816fc2896cb40ec7eb70632a0574931145761557eda09d9da206d
|
|
BLAKE2b-256 checksum How to use checksums |
b05974fde3227b61c4fcef82ec3fb6a011d9c7fa720c91036e4066aa88eef8d1
|
| 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 Oct 12, 2026.
Transparency logRelease files / dbworker-0.1.1-py3-none-any.whl
| Download URL | dbworker-0.1.1-py3-none-any.whl |
|---|---|
| Size | 11.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bcd88305d46056ddf077d4e4edc1efefe26a9c6dea96b4c2df539ea6922ee147
|
|
BLAKE2b-256 checksum How to use checksums |
d701c6169d68c4f96a8deedcf91a22e076bf08c5d92422e4bfe538803768058e
|
| 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 Oct 12, 2026.
Transparency log