Back to list
Postgres Lite の紹介: Node.js、Bun、およびブラウザ向けの純粋な JS 埋め込みエンジン
Introducing Postgres Lite: A Pure JS Embedded Engine for Node.js, Bun, and the Browser
Translated: 2026/3/14 14:00:48
Japanese Translation
🚀 Postgres Lite の紹介:Node.js、Bun、およびブラウザ向けの純粋な JS 埋め込みエンジン
PostgreSQL は間違いなく世界中で最も愛されるデータベースです。しかし、ローカルファースト開発、エッジコンピューティング、またはブラウザベースのアプリアプリケーションにおいては、私たちは通常 SQLite を選びます。なぜでしょうか? ブラウザ内で完全な PostgreSQL インスタンスを実行したり、ゼロ依存型の埋め込みプロセスとして Node.js/Bun で実行したりすることは、伝統的には困難でした—heavy WASM バイナリーまたはネットワークプロキシが必要です。今日は、Postgres Lite (PGLite) を紹介します:JavaScript エコシステム向けにネイティブで構築された、超軽量で高性能なインプロセス PostgreSQL エンジンです。
Postgres Lite は、純粋な TypeScript/JavaScript を使用して PostgreSQL ダイアルেকを実装したカスタム構築の SQL エンジンです。SQLite の代わりとして設計されており、'Postgres' を話すことが可能であるため、バックエンドからフロントエンドまたはローカル環境の同じスキーマ、クエリ、ロジックを使用できます。ゼロエミュレーション:WASM オーバーヘッドなし。ゼロ依存:純粋な JS/TS ロジックのみ。ユニバーサル:Bun、Node.js、およびモダンなブラウザで動作します(IndexedDB を介して)。
データベースエンジンからゼロで構築するには、SQL をパースするだけでなく、多くのことが必要です。Postgres Lite は、1M 件のレコード以上を簡単に対応できることを保証するために、いくつかの高度なデータベースエンジニアリング技術を実装しています:
他の単純な JSON ストアとは異なり、PGLite はスロット付きページアーキテクチャを使用してデータを固定された 4KB ページに整理します。これはフラグメンテーションを防ぎ、長さの異なるレコード(JSONB または TEXT など)の効率的な管理を可能にします。
プライマリキーとユニーク制約は、恒久的な B-Tree 実装によってバックアップされています。これは、データセットが数百万行に成長しても、ポイントルックアップが雷速であることを保証します。
データ完全性は妥協できません。PGLite は WAL(書き込みログ)を実装しています。どの更新も恒久的な .wal ファイルにログ記録された後、メインストレージに適用されます。プロセスがクラッシュしても、エンジンはその次の起動時に自動的に WAL を再生します。
PGLite はイテレータベースのプロセッシングモデルを使用しています。行は実行計画を一つずつ「引き抜かれます」。これは、million 行のテーブル上で SELECT * を実行する場合でも、すべて RAM に読み込みするのではなく、定数で最小限のメモリフットプリントを使用することを意味します。
洗練された LRU(最近使用されていないLeast Recently Used)キャッシュがメモリを管理し、頻繁にアクセスされるページをホットに保ちつつ、ディスクまたは IndexedDB への物理 I/O を最小限に抑えます。
npm install @pglite/core # または bun add @pglite/core
import { PGLite } from "@pglite/core";
import { NodeFSAdapter } from "@pglite/core/node-fs";
const db = new PGLite("app.db", { adapter: new NodeFSAdapter() });
await db.exec(`CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name TEXT NOT NULL, metadata JSONB)`);
await db.exec("INSERT INTO users (name, metadata) VALUES ($1, $2)", ["Alice", { role: "admin" }]);
const results = await db.query("SELECT * FROM users WHERE name = $1", ["Alice"]);
console.table(results);
import { PGLite } from "@pglite/core";
import { BrowserFSAdapter } from "@pglite/core/browser";
const db = new PGLite("browser_storage", { adapter: new BrowserFSAdapter() });
// それ以外はすべて同じ!
「Lite」という名前にもかかわらず、このエンジンは大規模な PostgreSQL シナックスのサブセットをサポートしています:
複雑なジョイン:INNER, LEFT, LATERAL, CROSS JOIN など。
高度なクエリ:CTE (WITH)、UNION、INTERSECT、サブクエリ。
ウィンドウ関数:ROW_NUMBER(), RANK() (OVER (PARTITION BY...) を介して)。
JSON パワー:JSONB オペレーター(->, ->>, @>, ?)の完全サポート。
アップセット:ON CONFLICT (col) DO UPDATE SET ...
📊 パフォーマンスベンチマーク
内部テストでは:
ポイントルックアップ (PK): ~0.2ms - 0.5ms。
シークエンススキャン:100k 行で < 40ms。
メモリ使用量:Volcano モデルのおかげで、重いクエリ負荷下でも一定です。
データベース愛好家や、より良い方法でローカルデータを処理するための JS 開発者であれば、プロジェクトを GitHub で確認してください!
https://github.com/pglite/pglite
JavaScript システムプログラミングの深掘りについて、フォローをお願いします!
postgres #javascript #typescript #database #bun #webdev #programming
Original Content
🚀 Introducing Postgres Lite: A Pure JS Embedded Engine for Node.js, Bun, and the Browser PostgreSQL is arguably the most loved database in the world. But when it comes to local-first development, edge computing, or browser-based apps, we usually reach for SQLite. Why? Because running a full Postgres instance in the browser or as a zero-dependency embedded process in Node/Bun has traditionally been hard—requiring heavy WASM binaries or network proxies. Today, I'm excited to introduce Postgres Lite (PGLite): An ultra-lightweight, high-performance, in-process PostgreSQL engine built natively for the JavaScript ecosystem. Postgres Lite is a custom-built SQL engine that implements the PostgreSQL dialect using pure TypeScript/JavaScript. It’s designed to be a robust SQLite alternative that speaks "Postgres," allowing you to use the same schemas, queries, and logic from your backend directly in the frontend or local environments. Zero Emulation: No WASM overhead. Zero Dependency: Just pure JS/TS logic. Universal: Runs in Bun, Node.js, and Modern Browsers (via IndexedDB). Building a database engine from scratch requires more than just parsing SQL. Postgres Lite implements several advanced database engineering techniques to ensure it can handle 1M+ records with ease: Unlike simple JSON stores, PGLite organizes data into fixed 4KB pages using a slotted-page architecture. This prevents fragmentation and allows for efficient management of variable-length records (like JSONB or TEXT). Primary keys and unique constraints are backed by a persistent B-Tree implementation. This ensures that even as your dataset grows to millions of rows, point lookups remain lightning-fast. Data integrity is non-negotiable. PGLite implements WAL. Every mutation is logged to a persistent .wal file before being applied to the main storage. If your process crashes, the engine automatically replays the WAL on the next boot. PGLite uses an iterator-based processing model. Rows are "pulled" through the execution plan one by one. This means a SELECT * on a million-row table uses a constant and minimal memory footprint instead of loading everything into RAM. A sophisticated Least-Recently-Used (LRU) cache manages memory, keeping frequently accessed pages hot and minimizing physical I/O to the disk or IndexedDB. npm install @pglite/core # or bun add @pglite/core import { PGLite } from "@pglite/core"; import { NodeFSAdapter } from "@pglite/core/node-fs"; const db = new PGLite("app.db", { adapter: new NodeFSAdapter() }); await db.exec(` CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, metadata JSONB ) `); await db.exec("INSERT INTO users (name, metadata) VALUES ($1, $2)", ["Alice", { role: "admin" }] ); const results = await db.query("SELECT * FROM users WHERE name = $1", ["Alice"]); console.table(results); import { PGLite } from "@pglite/core"; import { BrowserFSAdapter } from "@pglite/core/browser"; const db = new PGLite("browser_storage", { adapter: new BrowserFSAdapter() }); // Everything else is the same! Despite its "Lite" name, the engine supports a vast subset of Postgres syntax: Complex Joins: INNER, LEFT, LATERAL, and CROSS JOIN. Advanced Querying: CTEs (WITH), UNION, INTERSECT, and Subqueries. Window Functions: ROW_NUMBER(), RANK() via OVER (PARTITION BY...). JSON Power: Full support for JSONB operators (->, ->>, @>, ?). Upserts: ON CONFLICT (col) DO UPDATE SET ... 📊 Performance Benchmark In our internal tests: Point Lookups (PK): ~0.2ms - 0.5ms. Sequential Scan: 100k rows in < 40ms. Memory Usage: Constant under heavy query load thanks to the Volcano model. If you are a database enthusiast or a JS developer looking for a better way to handle local data, check out the project on GitHub! https://github.com/pglite/pglite Follow me for more deep dives into systems programming with JavaScript! postgres #javascript #typescript #database #bun #webdev #programming