- Published on
SQLite ルネサンス 2026 — 24歳の単一ファイルDBがなぜ最もホットなインフラになったのか (libSQL・Turso・LiteFS・D1・mvSQLite 徹底分析)
- Authors

- Name
- Youngju Kim
- @fjvbn20031
プロローグ — 24歳のデータベースがなぜまた熱くなったのか
2026年のインフラスタックを見ると、奇妙な光景が広がっている。一方では Postgres 18 がマルチマスタ論理レプリケーションを磨き上げ、もう一方では分散 NewSQL がグローバル一貫性を約束している。ところがもっとも騒がしいトレンドはそのどちらでもない — 2000年に D. Richard Hipp が単一ファイルの組み込みライブラリとして出した SQLite が、再び舞台の中央に立っている。
SQLite はデータベースではない。ライブラリだ。この復活の秘密はそこにある。
おかしく聞こえるが、もう一度考えてみよう。2026年インフラの二つのマクロ的な圧力は (a) エッジへ移動するコンピュート と (b) ローカルファースト UX である。答えは同じ — 「ネットワーク往復をなくせ」。そしてネットワークをなくすには、データがコードのそばになければならない。コードのそばにあるデータベースとは何か? ローカルファイル。SQLite は最初からローカルファイルだった。
本稿は、24歳の単一ファイル DB が 2026 年もっとも面白いインフラカテゴリーとして復活した過程を解剖する。何が新しいのか正確に — libSQL フォークと Turso のエンベデッドレプリカ、Cloudflare D1、日没した LiteFS、FoundationDB をバックエンドにする mvSQLite、Litestream のバックアップ — そして SQLite を「エッジデータベース」にしたトポロジーは何か。そして正直に語る — SQLite が正しい選択であるときと、絶対に間違った選択であるとき。
1章 · SQLite-at-the-edge テーゼ — なぜ今なのか
まず明確にしよう。SQLite は新しくない。 1.0 は 2000 年に出た。あらゆる Android、iOS、macOS、すべてのブラウザ、ほとんどの IoT 機器に入っている。世界でもっとも多くデプロイされているデータベースである。なのに、なぜ 2026 年に突然「トレンド」になったのか?
三つのことが同時に起きた。
第一に、エッジコンピュートがメインストリームになった。 Cloudflare Workers、Deno Deploy、Vercel Edge Functions、Fly.io — コードはユーザーの近くに移動した。ところでデータベースは? 依然として us-east-1 にある。ソウルのユーザーが東京のエッジで動く関数を呼び、その関数が us-east-1 の Postgres へ 200ms 往復したら、エッジの意味はなくなる。
第二に、ローカルファースト(local-first)運動が形を整えた。 Ink and Switch の 2019 年エッセイから始まった流れが、2026 年には実際の製品 — Linear、Figma、Notion の一部 — に結実した。「オフラインでも動き、即時で、自分のデータは自分の機器に」という約束。そのためには データがクライアントの中に なければならない。クライアントに入る組み込み SQL DB は? SQLite である。
第三に、「スケールアウトが答え」という神話が揺らいだ。 2020 年代前半、すべての会社が「分散分散分散」と叫んだが、2026 年にはほぼ全員が気づいた — ほとんどのアプリは分散一貫性を必要としない。1ノードに収まる。そして単一ノードのデータベースは、運用が嘘のようにシンプルだ。
この三つの交差点が SQLite である。ローカルファイルで、組み込みで、小さく、信頼できる。 そこに 2020 年代中盤の新しい道具が SQLite の弱点 — 分散、レプリケーション、バックアップ — を埋め始めたことが、このルネサンスの本質だ。
2章 · libSQL と Turso — 「エンベデッドレプリカ」という発明
この復活のもっとも影響力のある一つを選ぶなら、Turso のエンベデッドレプリカ(embedded replica) である。
libSQL — SQLite のオープンフォーク
SQLite 自体はオープンソースだが、外部コントリビューションを受け入れない。SQLite チームは「パブリックドメインだが、コードは自分たちが書く」という立場だ。これが渇望を生んだ — 人々は SQLite に新機能(ストレージバックエンドの差し替え、ネイティブレプリケーション、より良い同時性)を付けたかったが、道がなかった。
そこで 2022~2023 年頃、Turso(当時 ChiselStrike)が libSQL を作った。SQLite の本物のフォークである。MIT ライセンス、外部コントリビューションを受け入れ、そしてもっとも重要なのは — ネイティブネットワークプロトコル(HTTP、WebSocket via "Hrana")、ユーザー定義関数、そしてエンベデッドレプリカ を追加した。
エンベデッドレプリカ — モデルそのものが新しい
伝統的モデル: アプリ → ネットワーク → DB。すべてのクエリが往復する。
Turso のエンベデッドレプリカ: アプリの中に SQLite ファイルがある。読み取りはそのローカルファイルで起きる — マイクロ秒単位。書き込みはリモートのプライマリに送られ、プライマリが変更分(WAL フレーム)をバックグラウンドでプッシュしてローカルファイルを同期する。
+------------------------+ +------------------+
| アプリ (例: エッジ) | | Turso プライマリ |
| +------------------+ | 読み: ローカルDisk | (グローバル一次) |
| | libSQL クライアント+--+ < 1ms | |
| | + ローカル .db | | |
| +--------+---------+ | |
| | 書き (HTTP/Hrana) ------------->| |
| | <-- WAL フレーム (背景同期) | |
+------------------------+ +------------------+
何がそんなに新しいのか? 読み取りと書き込みの非対称性を、初めて正直に受け入れた。 ほとんどの Web アプリは 99% が読み取りだ。読み取りをミリ秒以下にできるなら、書き込みは往復を受け入れてもよい。ところが既存の「リードレプリカ」モデルは常にネットワーク越しにあった。Turso のエンベデッドレプリカは、そのレプリカを アプリプロセス内のディスク上のファイル に持ち込んだ。
コード: Turso エンベデッドレプリカのセットアップ
// pnpm add @libsql/client
import { createClient } from '@libsql/client'
const db = createClient({
// ローカル SQLite ファイル (ディスクに実在する)
url: 'file:local.db',
// リモート一次 — 書き込みはここへ
syncUrl: 'libsql://my-db-myteam.turso.io',
authToken: process.env.TURSO_AUTH_TOKEN,
// バックグラウンド同期の周期
syncInterval: 60, // 秒
})
// 最初の sync — リモート状態をローカルに複製
await db.sync()
// 読み取り — ローカルファイルから直接。ネットワークなし。
const rows = await db.execute('SELECT * FROM posts WHERE published = 1')
// 書き込み — リモートへ送られ、次の sync でローカルも追随
await db.execute({
sql: 'INSERT INTO posts (title, body) VALUES (?, ?)',
args: ['Hello', 'World'],
})
// 手動同期も可能
await db.sync()
このモデルの意味は大きい。もっとも大きいのは — 読み取りがローカルファイル IO と同じ速さ。SSD 上の SQLite インデックスルックアップはマイクロ秒単位。どんな分散 DB のキャッシュ層もこれには勝てない。トレードオフは 一貫性 だ。ローカルレプリカは最後の同期時点までのデータしか見えない。書き込み直後に自分のデータを即時に見る必要があれば read-your-writes モードを有効にする(その場合そのクエリだけはリモートに往復)し、強い一貫性が必要なワークロードはリモートモードを使うべきだ。
Turso プラットフォーム自体
Turso はその上にマネージドサービスを乗せた。寛大な無料枠(数億行が無料)があり、データベースブランチ がある(Git ブランチのように DB を分岐)、マルチリージョン一次も可能。2024 年以降の Turso の大きな賭けは per-tenant データベース — ユーザー1人につき1 DB。SQLite は軽いので、数十万個の小さな DB が可能。マルチテナンシーの新モデルだ。
3章 · LiteFS — Fly の分散 SQLite 実験と日没
Fly.io は 2022 年に別の答えを試した — LiteFS、FUSE ファイルシステムレイヤーである。
LiteFS のアイデア
普通の SQLite ファイルを FUSE マウントに置くと、LiteFS がそのファイルへの全トランザクション(WAL フレーム)を横取りして他のノードに複製する。アプリは 自分が分散環境にいることすら知らない — ただ SQLite ファイルを開くだけ。1つのノードが「一次」となり、すべての書き込みは一次へルーティングされる(LiteFS Proxy が自動処理)。他のノードはほぼリアルタイムで複製を受け取る。
最大の魅力は アプリコードの変更が不要な点 だった。Rails、Django、Phoenix — どのフレームワークでも、SQLite ファイルが開ければ LiteFS 上で分散モードで動いた。
日没
ところが 2024 年中盤、Fly は LiteFS の開発が事実上一時停止 されたと公知し、2025 年には新規ユーザーへ非推奨のシグナルが強まった(公式に「メンテナンスモード(maintenance mode)」と表現されることが多い)。技術的には FUSE 自体の複雑さ、マルチプライマリの難しさ、運用負担 が原因として挙げられた。Fly のマネージド SQLite ビジョンは別の方向(例: Fly Postgres の強化、Tigris のような外部パートナーシップ)へ移った。
それでも学べること
LiteFS の日没はアイデアの失敗ではない。LiteFS は 「SQLite をどう分散するか」に対するもっともクリーンな答え の一つだった。アプリ透過、単一一次、WAL レベルレプリケーション。マネージド製品として生き残れなかったとはいえ、libSQL と D1 がそのデザイン語彙の一部 — 一次 + 非同期レプリケーション、WAL フレーム単位の同期 — を引き継いだ。
今日、分散 SQLite を新規に始めるなら LiteFS は勧めない。しかし、設計ドキュメントは依然として読む価値がある。
4章 · Cloudflare D1 — エッジ SQLite のマネージド回答
Cloudflare の答えは違う。D1 は SQLite そのものを Workers ランタイムの近くに置く。
D1 のモデル
- 保存単位: SQLite データベース。
- ホスティング: Cloudflare のグローバルネットワーク上、一次リージョン + 自動リードレプリカとしてモデル化。
- アクセス: Workers バインディング(
env.DB.prepare(...))経由。HTTP API もあるが、主モデルは Workers 内部での呼び出し。 - 状態: 2026 年時点で GA であり、「Global Read Replication」オプションで読み取りレプリカが複数大陸に自動配置される。データベースあたりのサイズ上限は一桁 GB(現在 10GB 台)であり、巨大な単一 DB よりは per-application または per-tenant モデルに適する。
コード例: Workers + D1
// wrangler.toml に D1 バインディングがある前提
// [[d1_databases]]
// binding = "DB"
// database_name = "blog"
// database_id = "..."
export interface Env {
DB: D1Database
}
export default {
async fetch(req: Request, env: Env): Promise<Response> {
const url = new URL(req.url)
const slug = url.pathname.slice(1)
// prepare + bind — SQL インジェクション安全
const stmt = env.DB.prepare(
'SELECT title, body, published_at FROM posts WHERE slug = ?1 LIMIT 1'
).bind(slug)
const row = await stmt.first<{ title: string; body: string; published_at: string }>()
if (!row) return new Response('Not found', { status: 404 })
return Response.json(row)
},
}
ポイントは env.DB がネットワークハンドルではなく、ランタイムが注入するバインディング であること。Workers と D1 は同じインフラ上で動き、Cloudflare がルーティング・プーリング・レプリケーションをすべて隠す。開発者からは単に「エッジ関数の中に SQL がある」だけ。
トレードオフ
- 書き込み一貫性: 単一一次に直列化。マルチリージョン書き込みはない。グローバル一貫性は約束しない。
- トランザクション: インタラクティブトランザクションは制限的。バッチ API が推奨 — 複数 statement を一度にまとめて送る。
- サイズ: 1 DB あたり一桁 GB。それ以上のデータは R2 + D1 メタデータパターンで分割。
- ロックイン: D1 は Workers エコシステム内部でもっとも輝く。それ以外では魅力が薄れる。
D1 の真の価値は 「Workers を使うならほぼ摩擦なく永続性が手に入る」 という点。SQLite-at-the-edge のもっとも統合された実装である。
5章 · 分散 SQLite の別の道 — mvSQLite と rqlite
上の三つ(libSQL/Turso、LiteFS、D1)がメインストリームだが、より興味深い実験がある。
mvSQLite — FoundationDB でバック
mvSQLite は SQLite のストレージエンジン(VFS レイヤー)を丸ごと差し替えた。データはローカルディスクではなく FoundationDB に保存される。FoundationDB は Apple が使う分散トランザクショナル KV ストアで、直列化可能トランザクションと水平スケールを提供する。
結果: SQL インターフェースは SQLite そのまま、内部ストレージは分散トランザクショナル KV。単一 DB のサイズ上限が消え、複数ノードが同じ DB を同時に読み書きする。トレードオフは運用 — FoundationDB 自体の運用が容易ではない。
mvSQLite は本番採用が活発とは言いがたいが、「SQLite の API を維持しながらストレージだけ分散化する」 というデザイン語彙は強力だ。
rqlite — Raft の上の SQLite
rqlite は複数の SQLite インスタンスの前に Raft 合意アルゴリズム を置き、強い一貫性を作るシステムである。すべての書き込みは Raft リーダーへ向かい、ログがレプリケートされた後、各ノードの SQLite に適用される。
特徴:
- CP システム(CAP で一貫性優先)。
- クラスタサイズは通常 3~7 台。
- マネージドサービスではなく 自己運用 が基本。
- HTTP API として公開。
rqlite は大企業よりは エッジデバイス(IoT、産業ゲートウェイ)・小規模クラスタ・組み込み分散シナリオ で輝く。「本格的な分散 DB を運用するには小さいが、SQLite の単一ノードは危険な」ケースの正解だ。
比較が重要 — 同じではない
| システム | 一次設計軸 | 書き込みトポロジー | 一貫性 |
|---|---|---|---|
| libSQL / Turso | エンベデッドレプリカ + マネージド | 単一一次、非同期レプリケーション | 結果整合(read-your-writes オプション) |
| LiteFS | FUSE 透過レプリケーション(日没) | 単一一次、非同期レプリケーション | 結果整合 |
| Cloudflare D1 | エッジマネージド + 読みレプリカ | 単一一次、自動リードレプリカ | 結果整合(読み)、直列化(書き) |
| mvSQLite | FDB バック分散 SQL | マルチライタ、FDB 合意 | 直列化可能(FDB 保証) |
| rqlite | Raft 上の SQLite | リーダー書き | 線形化(Raft 保証) |
| プレーン SQLite + Litestream | 単一ノード + S3 バックアップ | 単一ライタ | (バックアップ・復元のみ) |
この表が核心 — 「SQLite ベース」という一語の下に、非常に異なるデザインが入っている。何を解決したいか が選択を決める。
6章 · Litestream — すべての基盤になった永続バックアップ
分散化を望まないなら? それでもバックアップは必要だ。Litestream がその位置を占めた。
何をするのか
Litestream は SQLite の WAL(Write-Ahead Log)を S3(または互換ストレージ)へほぼリアルタイムにストリーム する。サイドカープロセスとして動く。アプリは自分がバックアップされているか知らない。
# 一行セットアップ
litestream replicate /var/lib/app/data.db s3://my-bucket/backups/data.db
# 復元
litestream restore -o /var/lib/app/data.db s3://my-bucket/backups/data.db
復元は PITR(Point-in-Time Recovery)— 任意の過去時点に戻せる。RPO(復元時点目標)は通常秒単位。
なぜ重要か
Litestream は 「単一ノード SQLite は危険」という最後の正当化を破った。ディスクが死んでも、インスタンスが消えても、数分で S3 から復元される。運用モデルは衝撃的なほどシンプル — アプリ1個、SQLite ファイル1個、Litestream サイドカー1個。終わり。
LiteFS の日没後、Fly や他の PaaS は Litestream をより推す流れになった。「複雑な分散 SQLite より、単一ノード + Litestream のほうが 90% のケースに良い」という立場だ。
作者(Fly.io の Ben Johnson)は LiteFS も作った人 だが、本人がしばしば「ほとんどのアプリには Litestream で十分」と語る。洞察だ。
7章 · Bun SQLite + ネイティブランタイム SQLite — 復活のもう一つの軸
ランタイムレベルでも変化がある。
Bun の bun:sqlite
Bun は最初から bun:sqlite を 組み込みモジュール として提供している。同期 API、非常に速く、依存ゼロ。
import { Database } from 'bun:sqlite'
const db = new Database('app.db', { create: true })
db.exec(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
email TEXT UNIQUE,
created_at INTEGER DEFAULT (strftime('%s', 'now'))
)
`)
// Prepared statement — N 回呼んでもコンパイルは一度だけ
const insert = db.prepare('INSERT INTO users (email) VALUES (?)')
const tx = db.transaction((emails: string[]) => {
for (const e of emails) insert.run(e)
})
tx(['a@x.com', 'b@x.com', 'c@x.com'])
// クエリ
const all = db.query('SELECT id, email FROM users').all()
console.log(all)
なぜ新しいのか? Node.js 陣営では SQLite を使うには外部パッケージ(better-sqlite3、node-sqlite3)が必要だった。Node.js 22 以降は 実験的な node:sqlite が入った。ランタイムが SQLite を一級市民として受け入れ始めたのだ。
意味するところ
この流れが意味するのは — 「アプリの中に SQL DB がある」モデルがもう奇妙ではない。外部依存なし、一行のインポートで。これは上で見たエンベデッドレプリカモデルと自然に結びつく。ランタイム自体が SQLite を知り、ライブラリがその上で同期を行う。
Deno も、そしてあらゆる場所で
Deno も SQLite 標準モジュールを提供する。WASM ビルドの SQLite(sql.js、wa-sqlite)はブラウザで動く。すべてのランタイムが SQLite を知っている。この普遍性が SQLite を「交換標準」にする — 同じファイルをサーバ、クライアント、エッジがすべて読み書きできる。
8章 · ローカルファーストアプリ — SQLite が可能にしたパラダイム
ここまでが「サーバ側 SQLite の復活」なら、より大きな波はクライアントにある。ローカルファースト(local-first) アプリだ。
定義
Ink and Switch の定義を要約すると、ローカルファーストアプリは次を満たす:
- 即時(ネットワーク往復なし)。
- オフラインで動作。
- 複数機器で同期。
- 協業可能。
- データ所有権がユーザに。
- セキュリティとプライバシーがデフォルト。
- 長寿命(サービスが死んでもデータが生きる)。
そのためには データがクライアント内に永続的に なければならない。中の SQL エンジンは? SQLite だ。
二つの軸は異なる — 「ローカルファースト」と「CRDT」
よくある誤解を一つ指摘しよう。「ローカルファースト = CRDT」ではない。二つは直交する。
- ローカルファースト はデータトポロジーの約束 — データはクライアントにある、ネットワークなしでも動く。
- CRDT(Conflict-free Replicated Data Type) は複数のクライアントが同じデータを同時に編集するときの競合を解決するアルゴリズム。
協業がない、または単一ユーザが複数機器を使う場合(個人ノートなど)、単純な last-write-wins やベクタークロックで十分だ。CRDT は複数ユーザ同時編集(Figma、Linear など)で必要になる。
SQLite は ローカルファーストの永続化基盤 である。CRDT エンジン(Automerge、Yjs)や SQL ネイティブ同期エンジン(ElectricSQL、Replicache、PowerSync)がその上で同期を担当する。
SQL ネイティブ同期エンジン
- ElectricSQL — Postgres と SQLite の双方向同期。変更分が SQLite に溜まり、バックグラウンドで Postgres とマージ。競合は Rich-CRDT(オペレーションの登録済みツリー)で解決。
- Replicache (Rocicorp) — 独自データモデル。クライアントは IndexedDB(または SQLite-WASM)、サーバは push/pull エンドポイントだけを実装すればよい。
- PowerSync — Postgres ベース、クライアントは SQLite。ElectricSQL と競合・類似。
共通点: クライアントに SQLite、サーバに Postgres、その間の同期レイヤー。SQLite の復活はサーバサイドだけではなく、このクライアント-サーバトポロジーの一端を担う位置でも起きている。
9章 · SQLite が正しいとき、そして間違っているとき
ここまで見ると SQLite 万能論に聞こえかねない。そうではいけない。正直に見よう。
SQLite が正しいケース
- 読み取りヘビーで、トラフィックが 1 ノードに収まるアプリ。 ほとんどのウェブサイト、ほとんどの SaaS バックオフィス、ほぼすべてのブログ・ドキュメントサイト。「QPS が分間1万未満で単一インスタンスで十分」なら、しばしば SQLite が速い(ネットワーク往復がない)。
- エッジネイティブアプリ。 Cloudflare Workers + D1、Fly.io + Litestream モデル。データをコードのそばに置くのが自然。
- 組み込み・IoT。 産業ゲートウェイ、デバイスローカルロギング。SQLite の本業。
- ローカルファーストクライアント。 デスクトップ・モバイル・PWA アプリの永続ストレージ。
- per-tenant 分離。 テナント1人につき DB 1個。SQLite は軽すぎるので数十万個も可能。Notion・Linear・Turso の一部デザインパターン。
- 分析クエリのスクラッチ空間。 DuckDB のほうが向くが、単純なケースは SQLite でも十分。
- テスト環境の隔離 DB。 Postgres の代わりにインメモリ SQLite。速く、きれい。
SQLite が間違っているケース
- グローバル単一一次 + 複数地域同時書き込み。 1 DB に複数地域から同時にミリ秒以下で書き込みが必要なら、SQLite ベースシステムはほぼすべて単一一次だ。マルチリージョン書き込みは Spanner、CockroachDB、YugabyteDB、FoundationDB のような本物の分散システムの領域だ。
- 書き込みスループットが 1 コアを超える。 SQLite は書き込みに単一ライタロックがある(WAL モードでもトランザクション単位で直列化)。毎秒数万書き込みを持続するなら他のエンジンを見よ。
- トランザクションが非常に長く保持される OLTP。 長いトランザクションは他の書き込みをブロックする。Postgres の MVCC のほうがはるかに優雅。
- 巨大な単一 DB。 D1 は一桁 GB が限界、libSQL/Turso も数十~数百 GB は可能だが TB 級単一 DB は不自然。mvSQLite が答えになりうるが、その時点で分散 OLTP を再検討せよ。
- 複雑な分析クエリ(OLAP)。 SQLite オプティマイザは OLTP に最適化されている。大量分析は DuckDB・ClickHouse・Snowflake の領域。
- 多ライタアプリでデータ整合性を強く要求。 同時書き込み分離レベルが必要なら Postgres が正解。
- 全文検索ヘビー。 SQLite の FTS5 は優秀だが Elasticsearch・Meilisearch・Typesense レベルではない。
決定木
スタート:
単一ノードに収まるか? (例: 1万 QPS 未満、100GB 未満)
+-- はい -> 多地域分散が必要?
+-- いいえ -> SQLite + Litestream (もっとも単純)
+-- はい -> 読み/書きの比率は?
+-- 読みヘビー -> libSQL/Turso (エンベデッドレプリカ)
+-- 均衡 -> D1 (Workers なら) / Postgres + リードレプリカ
+-- いいえ -> ワークロードは?
+-- 分散 OLTP -> CockroachDB / Spanner / YugabyteDB
+-- OLAP / 分析 -> ClickHouse / Snowflake / BigQuery
+-- マルチテナント -> テナントあたり SQLite (per-tenant) を真剣に検討
この決定木でもっとも頻繁に答えになるのは 最初の分岐 だ — ほとんどのアプリは単一ノードに収まる。その事実を認めると、運用の単純さが爆発的に良くなる。
10章 · 運用の現実 — 何を本当に気にすべきか
SQLite ベースのシステムを運用する際によく遭遇する落とし穴。
WAL モードはデフォルトで
PRAGMA journal_mode=WAL;。同時読み書きスループットが劇的に良くなる。ほとんどのライブラリがデフォルトで有効にするが、自作セットアップなら確認せよ。
PRAGMA synchronous のトレードオフ
FULL(デフォルト): もっとも安全、もっとも遅い。NORMAL: WAL モードで推奨。非常に安全ではるかに速い。OFF: 危険。非推奨。
バックアップは無条件に Litestream または同等
単一ノード SQLite の最大リスクは ディスク・インスタンス損失。Litestream で分単位の RPO を確保せよ。EBS スナップショットも補完策として良い。
マイグレーションとアプリデプロイの分離
SQLite マイグレーションは通常速いが、大きなテーブルの ALTER TABLE はロックがかかる。大規模変更は新テーブル + バックフィル + スワップパターンを使え。
エンベデッドレプリカの同期周期
Turso エンベデッドレプリカで syncInterval を短く取りすぎると(例: 1 秒)、ネットワークと CPU を浪費する。通常 30~60 秒が良い出発点で、書き込み直後の即時性が必要な箇所では明示的な db.sync() や read-your-writes モードを使え。
per-tenant DB のメタデータ管理
テナントあたり DB 1個パターンを使うなら、「どのテナント DB がどのインスタンス・リージョンにあるか」のルーティングメタデータが必要だ。このメタデータ自体は1つの中央 DB(通常 Postgres またはより大きな SQLite)に置く。
エピローグ — 復活は偶然ではない
24 歳のライブラリがもっとも熱いインフラになったのは偶然ではない。三つのことが同時に起きた — エッジコンピュートの普遍化、ローカルファースト運動の成熟、そして「分散が答えとは限らない」という自覚。
本稿の一行要約: SQLite は新しい道具ではなく、新しいトポロジーを可能にした古い道具だ。libSQL/Turso のエンベデッドレプリカ、Cloudflare D1 のエッジ統合、Litestream のバックアップ基盤、Bun と Node のネイティブ SQLite — これらすべてが同じ方向を指す。データをコードのそばに置け。
チェックリスト — SQLite ベースシステムを始める前に
- 単一ノードに収まるか? (QPS、データサイズを見積もる)
- 読み/書きの比率を測定したか? (90/10 以上なら非常に有利)
- バックアップ戦略があるか? (Litestream または同等)
- WAL モード、
synchronous=NORMALを有効にしたか? - マイグレーションパターンを決めたか?
- 多地域が必要なら、libSQL/Turso または D1 を選んだか?
- 運用の単純さの利点が、他 DB の分散機能損失を相殺するか?
アンチパターン
- 「SQLite はおもちゃ DB」という偏見で始めもしない。 Notion、Linear、Cloudflare などが本番で使う。
- 逆に SQLite で全部解こうとする万能論。 9 章の「間違ったケース」を認めよ。
- バックアップなしの単一ノード SQLite。 ディスクは死ぬ。
- エンベデッドレプリカに強い一貫性を期待。 モデル自体が結果整合だ。
- 新規プロジェクトに LiteFS を導入。 日没の流れ。libSQL や D1 を見よ。
db.sync()を頻繁に呼びすぎる。 60 秒 + 明示呼び出しの組み合わせが普通良い。- すべての分散 SQLite システムが同じ保証を提供すると仮定。 表を見直せ — rqlite は線形化、Turso は結果整合、D1 は書き込み直列化 + 結果整合読み。
次の記事予告
次の二編では SQLite ルネサンスの姉妹トピックを扱う:
- ローカルファーストアプリ構築の実践 — ElectricSQL と PowerSync で Postgres ↔ SQLite 双方向同期を実装する。競合解決、オフラインキュー、モバイルクライアント。
- 2026 年のデータベース地図 — SQLite ルネサンス、Postgres 18 の新機能、DuckDB の分析侵攻、NewSQL の現実、そしてベクター DB が結局 Postgres に吸収されていく流れ。
24 歳の単一ファイルライブラリがもっとも面白い場所にいるという事実は、私たちの業界の真理を一つ再び教えてくれる — シンプルさは再びトレンドになる。十分長く待てば。
参考 / References
- SQLite Official Site — D. Richard Hipp の 24 歳の単一ファイル DB。
- libSQL on GitHub — SQLite のオープンフォーク、MIT ライセンス。
- Turso Documentation — マネージド libSQL、エンベデッドレプリカ。
- Turso Embedded Replicas Guide — モデル説明とコード例。
- The Future of LiteFS — Fly.io Community — 日没公知の背景。
- LiteFS on GitHub — アーカイブ近い状態だが設計ドキュメントとして価値。
- Cloudflare D1 Documentation — エッジ SQLite マネージドサービス。
- Making D1 Ready for Production — GA 発表記事。
- Cloudflare D1 Global Read Replication — グローバルリードレプリカ。
- mvSQLite on GitHub — FoundationDB ベース分散 SQLite。
- rqlite Documentation — Raft 上の SQLite。
- Litestream — SQLite の S3 永続バックアップ。
- Ben Johnson — Why I Built Litestream — 動機の説明。
- Bun SQLite — Bun のネイティブ SQLite モジュール。
- Node.js
node:sqlite— Node 22+ 実験的 SQLite モジュール。 - Local-first software — Ink and Switch — ローカルファーストの定義エッセイ。
- ElectricSQL — Postgres ↔ SQLite 同期エンジン。
- Replicache — クライアントサイド同期フレームワーク。
- PowerSync — Postgres ↔ SQLite 同期、ElectricSQL の競合・類似製品。
- SQLite WAL Mode — Write-Ahead Logging 公式ドキュメント。
- FoundationDB — mvSQLite のバックエンド分散 KV。