Hysen Labs
Open-source project
russellromney/honker avatar
russellromney

honker

SQLite extension + bindings for Postgres NOTIFY/LISTEN semantics with durable queues, streams, pub/sub, and scheduler

3,015 stars75 forksPythonNOASSERTION
DEEP OPEN-SOURCE ANALYSIS

honker: Postgres-style notify and queues for SQLite

honker adds Postgres-style notify and listen semantics to SQLite with durable queues, streams, pub/sub, and a scheduler, with no daemon or broker.

What honker adds to SQLite

honker is a SQLite extension plus language bindings that add Postgres-style notify and listen semantics to SQLite, with built-in durable pub/sub, a task queue, and event streams, and without client polling or a daemon or broker. Any language that can load the extension with `SELECT load_extension('honker')` gets the same features. It replaces queue-table polling with a single-digit-microsecond PRAGMA data_version read, and the default watcher checks every millisecond, giving push-like semantics and single-digit-millisecond cross-process delivery. You can raise the watcher interval when lower idle CPU matters more than lowest-latency wakeups. If SQLite is your primary datastore, the queue should live in the same file, so an insert into an orders table and a queue enqueue can commit in the same transaction and a rollback drops both. The quick start shows opening a database, making a queue, inserting an order, and enqueueing an email in one transaction, then a worker in another process claiming jobs. Simon Willison highlighted honker as a SQLite implementation of the transactional outbox pattern. The README labels it alpha software, better than experimental but not yet beta quality, which is an honest maturity signal for anyone planning to depend on it in production. The alpha label is an honest maturity signal, so a team knows to expect changes before building honker into a critical path that their users depend on every day.

Features and design

honker covers notify and listen across processes on one SQLite database file, durable at-least-once queues with retries, delayed jobs, priority, visibility timeouts, dead-letter rows, and task result storage, durable streams with per-consumer offsets, time-trigger scheduling with cron and interval expressions, named locks, rate limits, and transactional outbox helpers, plus SQL functions through a loadable extension. Bindings exist for Python, Node.js, Rust, Go, Ruby, Bun, Elixir, C++, .NET and C#, Java and JVM, and Kotlin. Deliberately excluded are workflow DAGs, task chains and groups and chords, multi-writer replication, and distributed locking across machines. The design rests on three pieces: ephemeral pub/sub with notify and listen, durable streams with offsets, and at-least-once queues with visibility timeouts and retries. All three are inserts inside your transaction, so the work row and the business row commit or roll back together. Because SQLite has no server-side push, honker uses a shared watcher that reads PRAGMA data_version every millisecond and, on change, listeners re-read indexed SQLite state. Overtriggering is intentional: one indexed select is cheap, while a missed wake is a correctness bug, so the design prefers spurious cheap wakes over missed deliveries. The excluded features mark the boundary of scope, so users with distributed needs should look at a different system instead of stretching honker past its single-file design.

SQL surface and architecture

The SQL extension exposes functions any SQLite client can call after loading honker and running honker_bootstrap. You can insert into a live table to notify, claim a batch of jobs, ack a batch, sweep expired jobs to a dead table, acquire and release named locks, try a rate limit, and compute next cron fire times for both five-field and six-field cron plus interval schedules. The scheduler registers periodic tasks and ticks to fire due ones, and streams publish, read since an offset, and save or get a consumer offset. Task results save with a time to live and sweep when expired. The extension shares tables with the language bindings, so a Python worker can claim jobs written by SQL, Node, Ruby, Go, or any other binding. The architecture uses one PRAGMA data_version watcher per database, with a default Rust-backed cadence of one millisecond that can be raised, and a counter change fans out a wake to each listener. Queue claim is one update returning through a partial index on queue, priority descending, run_at, and id where state is pending or processing, and ack is one delete. Retry-exhausted jobs move to a dead table so claim speed depends on active jobs, not old history. Language bindings default to WAL for concurrent readers with one writer. The partial index keeps claim speed tied to active jobs, which matters when a queue has accumulated history over months of operation on a busy production database.

Scope and ecosystem fit

honker is single-machine and file-backed by design. SQLite's locking model targets one host writing one database file, so two servers writing the same database over a network file system is not a honker deployment. The project compares itself to Postgres tools it admires: pg_notify gives fast triggers but no retry or visibility timeout, while pg-boss and Oban are the Postgres-side standards it chases on SQLite, and Huey is an excellent SQLite-backed Python queue. If you already run Postgres, the README says to use the Postgres tools. The transactional outbox idea owes much to Brandur Leach's staged job drains in Postgres. Honker does not ship framework plugins; you load the extension on your framework or ORM connection, run bootstrap, and call SQL functions inside the ORM's transaction, which works with SQLAlchemy, SQLModel, Django, Drizzle, Kysely, sqlx, GORM, ActiveRecord, Ecto, Hibernate, jOOQ, MyBatis, and Exposed. Performance on a modern laptop is thousands of messages per second, with cross-process wake latency set by the watcher cadence. Benchmarks include wake latency and a real bench with workers and enqueuers. The license is Apache-2.0 OR MIT, which gives downstream users a permissive choice. The Apache OR MIT choice gives downstream users a permissive option, which eases adoption in projects that already standardize on either of those two license families.

Editorial conclusion

honker is written in Python with a Rust core, is dual-licensed Apache-2.0 OR MIT, and its repository was last updated on 2026-08-24.

DEEP OPEN-SOURCE ANALYSIS

Official sources

Community notes

Community notes