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

SQLiteがあれば、耐久性のあるワークフローが実現できる

概要

  • DBOS は耐久性実行にPostgresだけで十分と主張
  • 一部のシステムでは SQLite でも十分な耐久性実現が可能
  • Litestream によるS3互換ストレージへのバックアップで可搬性を強化
  • AIエージェントや実験的ワークフローに最適な構成
  • 高可用性や共有スケールが必要な場合は Postgres 利用推奨

Postgres不要論からSQLite活用論へ

  • DBOS は、耐久性実行において Postgres があれば追加のオーケストレーション層は不要と主張
  • 筆者はこの方向性に賛同し、さらに進めて SQLite でも十分なケースが多いと提案
  • 多くの耐久性システムでは、本質的に必要なのは ワークフロー状態の保存 のみ
  • 計算リソース は安価で使い捨て可能な設計が望ましい
  • Obelisk のようなシステムでは、進捗は実行ログに記録され、履歴から再実行やリトライが容易
  • 最も重要なのは ワークフロー状態の持続性と可観測性

SQLiteが適している理由

  • SQLiteトランザクショナルな耐久性 をローカルで実現
  • 別途データベースサービスやネットワーク経由の制御面が不要
  • ローカルファイル で完結するため、運用負荷やコストを低減
  • 多くのシステムにとって ローカルDBファイル が最適な機構

Litestreamによる可搬性向上

  • 実験やデータが蓄積する場合、 SQLiteファイルの管理 が課題
  • Litestream を利用することで、 SQLiteの変更を非同期でS3互換ストレージへ転送 可能
  • 実行環境に近い状態で作業しつつ、バックアップや移行、検証も容易
  • 非同期レプリケーション のため、直近の書き込みが失われるリスクあり
  • 高可用性が必須な用途には向かないが、多くのAI・実験ワークフローには十分

エージェント型システムにおける利点

  • AIエージェント自動生成ワークフロー に最適
  • 各エージェントやテナントごとに 小規模で独立した状態管理 がしやすい
  • マイクロVMやコンテナ で小さなサーバー群を構築し、各自SQLite+オブジェクトストレージバックアップ運用
  • 常時稼働の大規模共有システムよりも シンプル・低コスト・障害分離性 が高い

Postgresを選ぶべきケース

  • SQLite が全てのケースに適しているわけではない
  • ObeliskPostgres もサポート
  • 高可用性大規模共有スケーラビリティ が必要な場合は Postgres が適切
  • オブジェクトストレージへの 非同期レプリケーション では不十分な場合も Postgres 推奨
  • 多くのワークフローシステムは初期段階で過剰なインフラを持つ必要はない
  • 多くのケースでは SQLite+Litestream+安価なワーカー で十分な耐久性システムを構築可能

まとめ:AIエージェント時代の新しいデフォルト

  • AIエージェント実験的システム では、 SQLite+Litestream 構成が最も合理的な選択肢
  • 必要最小限のインフラで 耐久性・可搬性・運用効率 を両立
  • 状況に応じて Postgres との使い分けが重要

Hackerたちの意見

Temporalを使ってワークフローの設定を始めたんだ。ローカルアプリとしては比較的軽量でデプロイできるよ。孤立したローカルインストールにはSQLiteを使ってる。APIのリトライやワークフロー、タスクの整理がすごく簡単になるんだ。ぜひ試してみてほしい。哲学的には、この記事が提案していることそのものだけど、エージェントが使うための非常にリッチで柔軟なインターフェースが追加されてる。さらに、ウェブUIがあって、ワークフローの確認やエージェントの実行状況を見たりするのがすごく簡単なんだ。Temporalはシステムに高い信頼性をほぼ無料で組み込んでくれるし、分散型で信頼性の高いシステムを作るのは難しいから、わざわざ車輪を再発明する必要はないと思う。SQLiteデータベースを簡単に調べたり、ワークフローの状況を把握したり、個別のタスクを組み合わせたり、ワークフローを簡単に呼び出せるようにしたいなら、Temporalをチェックしてみて。あと、エージェント用にファイルからはほとんど離れた感じ。MarkdownやJSONは素晴らしいけど、小さなローカルアプリを作る時には罠に感じることもある。LLMはSQLiteに強いし、MarkdownやJSONなど、好きなものを出力できるよ。エージェントが特定の行をクエリするだけで済むから、jqやgrepを使うよりもトークンをかなり節約できる。ファイルの束よりも、データの構造をきちんとするようにエージェントを促す、ポータブルで自己完結型のデータ管理システムが手に入るんだ。それに、もしローカルプロジェクトが成長したり、もっと正式になったりしても、MySQL/Postgresにスケールアップできるから、すでにデータのスキーマや規律が整ってるよ。

SQLiteを使う例を、jqやMarkdownをgrepする代わりに教えてくれない?

これ、Temporalの広告みたいだね :)

ファイルとデータベースのアプローチについて面白いね。いろいろ考えた結果、データベースに落ち着いたよ。

HNでの噂では、temporalのマネージドソリューションに予想以上のお金を払っているか、非常に重いシステムを自分で運営するためにかなりの運用負担を抱えているらしいね。私はどちらも経験していないからわからないけど、あなたや他の人の経験からもっと知りたいな。

SQLiteは、Postgresと比べてもシングルノードアプリケーションに対して驚くほどパフォーマンスがいいよ。Postgresはもっとメモリを消費して、IPCを通るためにIOが必要だけど、SQLiteなら共有接続プールでプロセス内に全てを保持できる。エージェントハーネスのためにいろんなストレージエンジンをテストしてるけど、SQLiteなら単一のvCPUで最大7,500の同時セッションが可能なんだ。Postgresはクラッシュしたり、接続が枯渇したりするけどね。

SQLiteは、Postgresと比べてもシングルノードアプリケーションに対して驚くほどパフォーマンスがいいよ。SQLiteがかなり優れたソフトウェアだと理解されている文脈では、そう期待すべきじゃない?シングルノードの文脈では、Postgresはオーバースペックだよ。SQLiteと競争できるとは期待すべきじゃない。これはほぼ、インメモリのHashMapをRedisとベンチマークして、理想的な条件でうまく動くことに驚いているようなものだね。

正しく使えば、SQLiteは実質的にプロセス内でのメソッド呼び出しみたいなもんだよ。もし障害物がランタイム、カーネル、ファイルシステム、そしてローカルのNVMeストレージデバイスだけなら、ホスティングされた代替品よりも圧倒的にパフォーマンスが良いことに気づくかも。スレッドを離れると、レイテンシの面で負けちゃうからね。SQLiteは、スレッド間通信を強制しなければ、マイクロ秒単位で動作できるよ。

本当に、実際のプロダクションアプリでSQLiteにこだわる理由がわからない。SQLiteは埋め込み型データベースで、同時実行性を管理するには全く向いてない。これがデータベースサーバー、例えばPostgresやMySQLの役割なんだ。彼らの仕事は、異なるマシンで複数のプロセスからデータを同時に変更できるようにすることだよ。これはコンピュータサイエンスの基本原則だと思う。「SQLiteで何でも」という人たちはちょっと経験不足な気がする。

これはコンピュータサイエンスの基本原則だ これがどうしてコンピュータサイエンスの基本原則なの?

あなたは、どんな種類の並行性があるか、そしてそれにどう応じるのがベストかについて、かなり限られた理解をしているみたいだね。サーバーかどうかは、この議論にはあまり関係ないよ。SQLiteは、多くの実際のワークロードにとって優れたプロダクションDBであることは広く知られていることだし。Postgresとは全然違うから、新しいスキルセットを学ぶ必要があるよ。考え方の一つとしては、SQLiteは自然に強いパーティショニングがあるシステムの部分でうまく機能するってことだね。

コンピュータサイエンスは、物理学が橋を作ることだけに関わるのと同じように、具体的なソフトウェアに手を出すことはないよ。「コンピュータサイエンスの基礎原則」ではないんだ。

1つのSQL DBをゴルーチンごとに割り当てることで、すごく良い結果が出たよ。アクセスは事前にシリアライズされていて、非常に高いボリューム(130Kリクエスト/秒)のサービスだったんだ。正確なトランザクション性は製品の目標ではなかったし、SQLiteはメモリ内の状態をバックアップするためだけに使ってた。もしアボートとかで少し失ったとしても、それは問題なかったよ(ただし、通常のメンテナンスではSIGTERMをキャッチしてリスンを停止し、フライト中のコールを待ってから残りの変更をSQLiteにフラッシュしてた)。起動時にはSQLiteをメモリに読み込んでリスンを始める前にデータを埋め込んでた。コンテナの実行間での永続ストレージがあって、同時に同じファイルへの読み書きはしないようにしてたんだ。(行数の制限に達するとDBを閉じて新しいのを開くようにして、ディスクがいっぱいにならないようにしてた。SQLiteの最大サイズは、メモリから提供されるLRUマップの最大サイズに対応してた。A/Bを「メモリに保存されたデータがいっぱい」と「現在更新中の状態」の間で切り替えてた。再起動やメンテナンス中の一時的な永続性のためにプロトバフをディスクに書き出す必要がなくて、ずっと楽だったよ。

だから、SQLiteのデータベースが数十億もあるんだよね?SQLiteは他のすべてのデータベースエンジンを合わせたよりも多く使われてると思う。野生には数十億のSQLiteのコピーが存在するんだ。SQLiteは以下のものに見られるよ:すべてのAndroidデバイス、すべてのiPhoneとiOSデバイス、すべてのMac、すべてのWindows 10/11インストール、すべてのFirefox、Chrome、Safariウェブブラウザ、すべてのSkypeインスタンス、すべてのiTunesインスタンス、すべてのDropboxクライアント、すべてのTurboTaxとQuickBooks、PHPとPython、ほとんどのテレビとセットトップボックス、ほとんどの自動車のマルチメディアシステム、無数の他のアプリケーション。 https://sqlite.org/mostdeployed.html

SQLiteと並行フロントエンド(例えばGoのnet/httpサーバー)を組み合わせることで、サービスが扱う必要があるすべての負荷を処理できるケースはたくさんあるよ。特に、時間をかけてハードウェアをスケールアップできるならね。SQLiteは、何百何千のTPSにスケールアップするのも簡単だよ。本当に失うのはHA/フェイルオーバーとDRだけ。でも、それに対処するためのソリューションもあるし、単一サーバーシステムは意外と頑丈なんだ。非常に複雑なコントロールプレーンがない限り、システムが増えると稼働時間が減るからね。

Sqliteは色々なことに使えるけど、君は多分、ネットワークデータベースでシャーディングをしたいような大規模なウェブアプリに集中してるんじゃないかな。それも一つの分野で面白いけど、他にもたくさんあるよ。技術の変化に応じて以前の「ベストプラクティス」を再評価するのが好きなんだ。特にシンプルさを向上させる方法でね。家族のソーシャルメディアサイトをVPS上の単一のsqlite DBで運営するのは最高だよ。ユーザーは約15人で、メンテナンスはほぼゼロ。FreshRSSのインスタンスもsqliteで動かしてるし、「今」のページもそう。仕事では、過去数十年にわたって色々なことにsqliteを使ってきたよ。アドホックなジョブキューとして、ローカルで大量のログを取り込んでクエリするための手っ取り早い方法として、そしてsimonwの素晴らしいhttps://github.com/simonw/datasetteを使ってリアルタイムで表示・フィルタリングするためにね。「sqlite for everything」っていうよりは、「思いつかなかった場所でsqliteを使う」って感じだと思う。kentonv/Cloudflareのエッジでのsqliteに関する取り組みがこの考え方をちょっと人気にしたかもしれないけど、元々はあったことだよ。https://blog.cloudflare.com/sqlite-in-durable-objects/ こういう小さな事例を知っていて、それにsqliteを活用したいと思うのは、経験の指標かもしれないね。

あなたは私のエンタープライズ顧客の一人ですか?もしあなたのワークロードが書き込みの同時実行を必要としない場合はどうしますか?

スケールゼロはめっちゃ便利だよね。

実際にSQLiteの上で動いてる本番アプリがどれだけあるか知ったら、驚くと思うよ(Cloudflare D1経由でね)。

Litestreamの5.9以降のリリースには、インスタンスが異常な量のデータを同期するバグがあるんだ。データが1万未満で、ほとんど書き込みや読み込みがないDBでも、毎日10GBくらいのレプリケーショントラフィックが発生する。おもちゃプロジェクトには無駄に高くついちゃった。

次のアイデアの進化版が「ログだけで耐久性のあるワークフローが実現できる」ってのを見るのが待ちきれないよ。

ログだけで耐久性のあるワークフローが実現できるの?ちょっと混乱してるんだけど。ログを使ってネストされたデータや関連データをどうやって永続化してクエリするの?ログって、ElasticsearchやMeiliSearchみたいなものを指してるのかな?

すぐに続いて「耐久性のあるワークフローにはソケットが全てだ」とか「耐久性のあるワークフローにはカーネルのプリミティブが全てだ」とか言われるけど、真面目な話、プロフェッショナルであることの一部は、仕事に適したツールを使うことだよね。

ファイルからマルチパーティションデータベースへのギャップはかなり大きいよね。コンテナでデータベースを運営するのは、実際のプロダクションのことがあるときは私には向いてないな。個人的には、ETLの多くはエンタープライズデータベースを使わずにローカルで処理できると思う。そういう場合、DuckDBはSQLiteより5倍から10倍も優れていて、専用のPostgresデータベースを立ち上げるよりもずっとシンプルで速いよ。一般的なスクリプトでは、20行のawkスクリプトとDuckDBに基づいたもっとクリーンで堅牢、メンテナブルなSQLスクリプトを比べると、比べ物にならないね。MotherDuckがIPOのためにポンプ・ダンプする必要がないことを願ってるよ。企業の欲に振り回されて、そのツールを失うのは悲しいから。

こんにちは、DuckDBの開発者関係者です。まず、優しい言葉をありがとう :) 次に、20行のawkスクリプトについて言及してくれて面白いね。昨日、Ubuntu Summitで似たようなことを話してたんだ。ある時点で、GNU coreutilsを使ったシェルスクリプトは実用的じゃなくなるけど、DuckDBのSQLスクリプトは複雑さやメンテナンス性(しばしばパフォーマンスも)においてスケールしやすいんだ。私のスライドはここにあるよ: https://blobs.duckdb.org/slides/duckdb-ubuntu-summit-2026.pd...(32ページから36ページ)。それから、MotherDuckはDuckDB上でクローズドソースのDBaaSを開発しているよ。彼らはDuckDBを基にしていて、DuckDBでMotherDuckに接続するけど、シアトルに本社を置く別のVC資金調達された会社なんだ。DuckDBはアムステルダムにある自己資金で運営されているDuckLabsによって開発されているよ。そして、このプロジェクトのIPはオランダの非営利団体DuckDB Foundationにあるんだ。詳しくは、https://duckdb.org/faq#how-are-duckdb-the-duckdb-foundation-...

Postgres ... は、より高い可用性や広範な共有スケーラビリティ、またはネットワークデータベースによってより良く提供される他のデプロイメント特性が必要な場合に適切な選択です。また、オブジェクトストレージへの非同期レプリケーションが望む耐久性モデルでない場合にも適しています... 多くのワークフローシステムは、初日からそれを必要としないし、実際の状態が要求する以上のインフラから始めるべきではないと思う。 ------ こういうYAGNI的な考え方はよく見るけど、私の見解では、エッジケースを解決するためにかける努力と、現在のアーキテクチャを自分のユースケースに適応させる努力のバランスを取るべきだと思う。Sqliteをデプロイして、それが単独で良いと思っていたら、想定外の課題に直面することになるかもしれない。そうなると、それに対処するために貴重な時間と労力を費やさなければならない。で、使いこなせなくなったら、Postgresでも同じことをするためにさらに貴重な時間を費やす必要がある。だから、アーキテクチャに関しては、私はますますオーバーエンジニアリングしてしまうことが多いんだ。近い将来にアーキテクチャをアップグレードする可能性が高いと仮定すると、そのアプローチは実際には非常に効率的だと思う。潜在的な問題をたくさん見つけることができるし、それが現在のシンプルなアーキテクチャがどうあるべきかを考える助けにもなる。今後の道筋もよく理解できるし、今は意味がある方向に深く進みすぎて、数年後にすべてを捨てなければならないことを避けることができる。AからB、BからC、CからDに進むのは、それぞれが今のところ十分な最適なアーキテクチャだけど、安定させたり問題を解決するために多くの作業が必要なのに比べて、Dを十分に探求して、今A、B、Cのどれを構築すべきかを知る方がずっと効率的だよ。基本的に、適切に行われるオーバーエンジニアリングは無駄ではない。効率的に扱っていることの核心に切り込んで、今どうやって開発リソースを最適に配分するかを、(多分)シンプルな選択をすることを可能にしてくれるんだ。

何年もSQLiteについて読んでから、家のプロジェクトで使い始めたんだけど、Postgresから来たせいか、型システムの貧弱さに衝撃を受けたよ。ほんとに劣ってるし、なんでこんなに評価されてるのか分からない。 https://sqlite.org/datatype3.html https://www.postgresql.org/docs/current/datatype.html 日付や時間を扱うのが、まるで30年前のデータベースを使ってるみたいで、挿入時に何も強制されないんだ。ほんと、なんでこんなに多くの人が好きなのか説明してほしい。

そう、これがSQLiteに対する唯一の不満だね。厳格な型システムのSQLiteがあったら最高なのに。

それが一つのファイルなんだよね。

厳格なテーブルも使えるよ。 https://sqlite.org/stricttables.html

ドキュメントを読んでみて。

型システム以外の部分で評価されてるよね。特に厳密なテーブルがないと、がっかりするのは分かる。DuckDBをチェックしてみて。基本的にはSQLiteだけど、ちゃんとした型があるから。とはいえ、OLAP(配列の構造体)だから、OLTP(構造体の配列)よりも典型的なSQLiteの負荷にはパフォーマンスが悪いかもしれないけどね。実際、どっちを考えてるアプリケーションなら、あんまり関係ないと思うよ。

状態を非クリティカルなセクションで維持する必要があるアプリケーションがあったり、SQLを使うのが実は良いアイデアだと気づいた場合(クリティカルなセクションでも)、SQLiteはいい選択肢だし、脆弱なカスタムソリューションを考える時間を大幅に節約できるよ。 メモリ内のSQLiteデータベースを維持して、SQLコマンドで操作することができるし、アプリケーションの再起動間で状態を保持したいなら、定期的にディスクに保存したり、そこから読み込んだりもできるよ。 https://www.sqlite.org/backup.html#example_1_loading_and_sav... 「これが、今まで扱った中で最も便利なファイルフォーマット(アプリケーションフォーマット)でもあるんだ。」

いろんな大手のPostgresクラスターからSQLiteに移行したんだけど、我々は7桁のMAUがいて、すべてSQLiteの耐久オブジェクトで支えられてる。 アクセスパターンについては考え方を変えなきゃいけないけど、得られるメリットはそれだけの価値があったよ。