世界を動かす技術を、日本語で。

Honker – SQLiteファイル内の耐久性のあるキュー、ストリーム、パブ/サブ、及びcronスケジューラー

2026年4月30日原文(honker.dev)

概要

honker は、 SQLiteファイル内 で耐障害性キュー、ストリーム、pub/sub、cronスケジューラを提供。 Postgres風のNOTIFY/LISTEN を実現し、 追加ミドルウェアやデーモン不要複数言語対応 で同一ファイル・同一フォーマットを共有。 トランザクション一貫性 で、ビジネスデータとキュー操作を同時に管理可能。 運用コスト削減低レイテンシ を両立。

honker:SQLiteで実現する耐障害性キュー・ストリーム・Pub/Sub・Cron

  • honker は、 SQLiteファイル に耐障害性キュー、ストリーム、pub/sub、cronスケジューラを統合
  • PostgresのNOTIFY/LISTEN のような通知セマンティクスを SQLite にもたらす
  • クライアント側ポーリング不要デーモンやブローカー不要 の設計
  • クロスプロセスのウェイクレイテンシ約0.7ms(MシリーズMac) の高速応答
  • SQLite拡張として提供、どの言語でもSELECT load_extension('honker_ext')で利用可能
  • Python、Node、Rust、Go、Ruby、Bun、Elixir バインディングが 共通オンディスクフォーマット を共有

SQLiteを主データストアとする利点

  • Bluesky’s PDS、Fly’s LiteFS、Turso など実運用例多数
  • SQLite利用アプリ では 耐障害性キュー が不可欠
  • 従来は Redis+Celery などを追加導入し、 二重管理や運用負荷増加 が発生
  • honker は「 キューも同一SQLiteファイル内」という設計思想
    • INSERT INTO ordersqueue.enqueue(...)同一トランザクション で実行
    • ロールバック 時は 両方とも巻き戻し、一貫性確保
    • キューはテーブルの行 として管理、 パーシャルインデックス で高速アクセス

マルチ言語・シンプルなAPI

  • 同一.dbファイル・同一フォーマット7言語 サポート
    • Python、Node、Rust、Go、Ruby、Bun、Elixir、C++、SQL(拡張)
  • Python例
    • 同一トランザクション でビジネスデータとキュー投入
    • ワーカーはコミット時に自動ウェイクポーリング不要
    • Huey風デコレータ でタスク定義・再試行・タイムアウトも簡単

内部動作とパフォーマンス

  • PRAGMA data_version1msごとにポーリング
    • SQLiteのコミットごと にインクリメントされる 単調カウンタ を利用
    • 3μsで読める ため 高効率なウェイク信号
    • 1データベース1ポーラースレッド、リスナー数が増えても負荷一定
    • SELECTのみページキャッシュ負荷・ロック競合なし
    • リスナー数増加によるスケールも容易

ACIDトランザクションと拡張性

  • キューやストリーム、pub/sub拡張が管理するテーブルへのINSERT
  • queue.enqueue(payload, tx=tx)ビジネスロジックと同一トランザクション
  • ロールバック時はジョブも同時に消去、整合性維持
  • pg_notify は高速だが リトライや可視性なし
  • Huey (SQLiteバックエンドPythonタスクキュー)から多くを参考
  • pg-boss、Oban はPostgres向け標準、Postgres利用者はそちら推奨

導入方法

  • Python例:pip install honker
  • Node、Rust、Go、Ruby、Bun、Elixir、C++ 等でも利用可能
  • SQLite拡張 として 既存ワークフローに容易に統合

honker導入による運用コスト削減と一貫性の強化

  • 追加ミドルウェア不要 による 運用・保守コスト削減
  • ビジネスデータとキューの同時管理データ一貫性 を実現
  • 低レイテンシ・高スケーラビリティ本番運用にも最適
  • SQLiteを主データストアとするアプリ における 耐障害性キューの最適解

Hackerたちの意見

数日前の議論: https://news.ycombinator.com/item?id=47874647

面白いアプローチだし、新しいプロジェクトに使うと結構楽しいかもね。 > どうやって動くかというと、honkerはSQLiteのPRAGMAデータバージョンを毎ミリ秒チェックするんだ。これは、SQLiteがどの接続、ジャーナルモード、プロセスからでもコミットするたびに増加する単調カウンターで、正確なウェイク信号のために約3µsの読み取りが必要なんだ。

最後にこう書いてあるね: "pg-bossとObanはPostgres側のゴールドスタンダード" でも、Obanは今SQLiteもサポートしてるよ。 https://github.com/oban-bg/oban

あと、Graphile Workerってのもあるよ。 https://github.com/graphile/worker

"アイドルコストは、データベースごとに毎ミリ秒1回の軽量SELECT" って言ってるけど、これを書いたLLMはちょっと行き過ぎたと思う。忙しくSELECTをポーリングするのが、"カーネルファイルウォッチャー"より良いとは思えないんだよね。

"毎ミリ秒1回の軽量SELECT" って、ちょっと妊娠したって言ったティーンエイジャーを思い出すな。

うん、同じ直感があったよ。これは「いいアイデア」って感じだけど、実行がイマイチだね。つまり、こんな風にSQLiteを叩くくらいなら、もうRedis使った方がいいんじゃない?

データベースに変更を加えてないなら、SELECTって意味あるの?変更してるなら、ファイルウォッチャーが起きた後はポーリングしなきゃいけないんじゃない?WALモードだと、SQLiteは共有メモリをちょっと見ればこのクエリに応えられると思うけど、確かに忙しい待機状態だね。

俺には、カーネルファイルウォッチャーを作らないように頼まれたみたいに聞こえるけど、実装には全く関係ないのに、どこにでもそのことを書いてるのが気になる。

1ミリ秒ごとに軽量なSELECT 一分あたりたったの1ドルで、スーパーカーをリースできるよ。

敬意を表して(ありがとう、笑) - そうかもしれないですね。最初の意図はinotify的なものを使うことでしたが、最初からプラットフォームごとの違いを避けました。これは間違いなく楽しみのためのプロジェクトで、意図せず大きくなってしまったので、強化や改善に取り組んでいます。Flyが大好きです。

RailsのLitestackを思い出すな。結局、Rails自体がSQLiteに全力を注ぎ始めたから、放棄されたんだよね。 https://github.com/oldmoe/litestack

Hacker Newsで議論の続きを見る