Rustでローカルデータを扱うとき、SQLiteに収まりきらないPostgreSQL固有の機能(pgvector、JSONB、配列型など)が必要になることがある。しかしDockerやサーバープロセスを都度用意するのは面倒だ。そのギャップを埋めるOSSクレートが pglite-oxide だ。
この記事では、ElectricSQL PGliteをWasmtime経由でRustアプリに直接埋め込む仕組みと使い方を解説します。2026年4月26日にリリースされたv0.3.0の変更点もあわせて紹介します。
この記事でわかること:
- pglite-oxideが解決する課題とアーキテクチャ
PgliteとPgliteServer— 2つのAPIの使い分け- Tauriデスクトップアプリへの組み込み方
- v0.3.0で強化された起動コスト削減の仕組み
pglite-oxideとは
pglite-oxideは、ElectricSQL PGliteのWASI版PostgreSQLランタイムをWasmtime経由でRustアプリに埋め込むOSSクレートです。PostgreSQL 17.x互換のデータベースをRustバイナリに同梱でき、Docker不要、Node.js不要、外部プロセスのサイドカーなしで動作します。
PGliteはPostgreSQLをWebAssemblyにコンパイルしたもので、もともとブラウザ上でPostgresを動かすためにElectricSQLが開発しました。pglite-oxideはそのWASI版をRustのWasmtime内で実行し、Rustコードから直接呼び出せる形に仕上げています。Rust 1.92以降とWasmtime 44が必要です。ライセンスはMIT / Apache-2.0 / PostgreSQLのトリプルライセンスです。
解決する課題
RustでローカルにPostgres互換のDBを使いたい場合、これまでの選択肢は主に2つでした。
Dockerまたは外部Postgresサーバー: 開発環境や配布物に外部依存が生まれ、エンドユーザーへの配布が難しくなります。embedded-postgresクレート: ネイティブバイナリを含む大きなバンドルになりがちで、環境によってはNode.jsが必要です。
pglite-oxideはWASMランタイムを使うことで、単一クレートの依存を追加するだけでRustバイナリにPostgreSQLが内包されます。特に以下の用途で効果を発揮します。
- TauriなどのデスクトップアプリへのローカルDB組み込み
- Dockerなしの高速なPostgresバックエンドテスト
- pgvectorを使ったRAGのローカルプロトタイプ
- SQLx・tokio-postgres・DieselなどPostgreSQL URIを期待するクレートとの連携
2つのAPI
pglite-oxideは用途に応じた2つのエントリーポイントを提供しています。
Pglite — 直接埋め込みAPI
Rustコードがデータベース呼び出しを直接所有する場合に使います。execがパラメータなしSQL、queryがserde_json::Valueを渡す拡張プロトコル対応クエリです。
use pglite_oxide::Pglite;
use serde_json::json;
let mut db = Pglite::open("./.pglite")?;
db.exec("CREATE TABLE IF NOT EXISTS items(value TEXT)", None)?;
db.query("INSERT INTO items(value) VALUES ($1)", &[json!("hello")], None)?;
let result = db.query("SELECT value FROM items", &[], None)?;
db.close()?;
テスト用の一時DBはPglite::temporary()で作成します。内部でプロセスローカルのテンプレートクラスタをクローンするため、毎回の初期化処理を省けます。一般的にPgliteServerよりもPgliteの使用が推奨されています。
PgliteServer — PostgreSQL URIサーバー
既存クレートがPostgreSQL接続URIを期待している場合に使います。内部でローカルTCPまたはUnixソケットサーバーを起動し、接続URIを発行します。
use pglite_oxide::PgliteServer;
let server = PgliteServer::temporary_tcp()?;
let url = server.connection_uri();
// SQLx や tokio-postgres にそのまま渡せる
1バックエンドを1接続で扱う設計のため、SQLxなどのコネクションプールはmax_connections(1)で設定します。永続DBの場合はPgliteServer::builder().path("./.pglite").start()?で起動します。
Tauriデスクトップアプリへの組み込み
Tauriアプリでは、データベースインスタンスをRust側の管理ステートとして保持し、コマンド経由でアクセスするパターンが推奨されています。
use pglite_oxide::Pglite;
use serde_json::json;
use std::sync::Mutex;
use tauri::State;
struct Db(Mutex<Pglite>);
#[tauri::command]
fn add_item(db: State<'_, Db>, value: String) -> Result<(), String> {
let mut db = db.0.lock().map_err(|e| e.to_string())?;
db.query(
"INSERT INTO items(value) VALUES ($1)",
&[json!(value)],
None,
)
.map_err(|e| e.to_string())?;
Ok(())
}
プラットフォームのアプリデータディレクトリに保存する場合は、Pglite::builder().app("com", "example", "my-app").open()で開くと各OSの適切な場所に自動配置されます。v0.3.0にはバニラTauri v2でSQLxプロファイラを組み合わせたサンプル(examples/tauri-sqlx-vanilla)が追加されており、リリースモードのワークロード時間を実測できます。
v0.3.0の主な変更点
2026年4月26日にv0.2.0とv0.3.0が同日リリースされました。v0.2.0でPglite・PgliteServerの高レベルAPIが整備され、v0.3.0ではそれをベースに起動コストの大幅削減が行われています。
コンパイル済みモジュールキャッシュ: WasmtimeエンジンとモジュールをRustプロセス内で再利用できるようになり、2回目以降のPgliteインスタンス生成でWASMコンパイルをスキップします。さらにディスク上の.cwasmキャッシュにも保存されます。キャッシュキーにはPGlite WASMのSHA-256・Wasmtimeのメジャーバージョン・ターゲット・設定IDが使われるため、バイナリ更新後に古いキャッシュが誤って再利用されません。
埋め込みPGDATAテンプレート: 事前初期化済みのPGDATAテンプレートをクレートにバンドルし、マニフェスト検証付きでクラスタを素早く作成できるようになりました。新規DB起動時のinitdb相当の処理を丸ごとスキップできます。
ブレーキングチェンジ: PgliteRuntimeOptions::defaultが最適化済みの埋め込みテンプレート起動パスを選択するようになりました。ensure_clusterはランタイムオプションが必須引数になっています。v0.2.0から移行する場合はこの点の確認が必要です。
インストールと始め方
cargo add pglite-oxide serde_json
コマンドひとつで依存関係が追加されます。バンドルされたPGDATAテンプレートとコンパイル済みWasmtimeモジュールのキャッシュをデフォルトで使うため、追加の設定フラグは不要です。詳細な使用例は公式ドキュメント(Usage Guide・Tauri Guide)を参照してください。