Python
Install
Section titled “Install”pip install honkerThe wheel bundles the native extension on supported platforms, so normal
Python apps do not need a separate libhonker_ext file.
import honker
db = honker.open("app.db", watcher_backend="shm")Use watcher_backend="polling" for the stable default, "kernel" for
filesystem wake hints, or "shm" for the SQLite WAL-index fast path.
Experimental backends must be compiled into the package and available for the
database path.
q = db.queue("emails")q.enqueue({"to": "alice@example.com", "order_id": 42})
job = q.claim_one("worker-1")if job: send_email(job.payload) job.ack()Transactional Outbox
Section titled “Transactional Outbox”Use the outbox when the durable database commit should trigger an external side effect such as email, webhooks, cache invalidation, or search indexing.
outbox = db.outbox("email", lambda payload: send_email(payload))
with db.transaction() as tx: tx.execute("INSERT INTO orders (id, total) VALUES (?, ?)", (42, 9900)) outbox.enqueue({"order_id": 42}, tx=tx)
await outbox.run_worker("email-worker")The outbox is just a reserved Honker queue named _outbox:<name>, so another
Python process can deliver jobs after the writer exits.
ORM Section
Section titled “ORM Section”For SQLAlchemy, SQLModel, or Django, keep the ORM transaction as the owner of
your business write. Load the Honker extension on the same SQLite connection,
then call honker_enqueue, notify, or stream SQL functions inside
that transaction.
from sqlalchemy import text
with Session(engine) as session, session.begin(): session.execute(text("INSERT INTO orders (id, total) VALUES (:id, :total)"), {"id": 42, "total": 9900}) session.execute( text("SELECT honker_enqueue(:queue, :payload, NULL, NULL, 0, 3, NULL)"), {"queue": "emails", "payload": '{"order_id":42}'}, )See the full Python ORM recipe for extension loading, typed payloads, and Django connection hooks.
Testing
Section titled “Testing”Use tmp_path / "test.db" rather than :memory:. Cross-process workers and
watchers need file locking, WAL, and reopen semantics that in-memory SQLite
cannot model.