pglite: Running PostgreSQL in the Browser with WebAssembly
pglite compiles full PostgreSQL to WebAssembly, enabling real SQL capabilities directly in browsers, Node.js, Bun, and Deno—with only 3MB gzipped size and support for extensions like pgvector.

As a Java veteran who’s been through the wringer with Spring Boot, MyBatis, and every ORM under the sun, my first reaction to pglite was: “PostgreSQL running in the browser? Come on—is this just another SQLite wrapper dressed up as something fancy?”
But after reading the README, I was stunned—it’s legit. The team compiled the entire PostgreSQL into WebAssembly (WASM) and made it run natively in browsers, Node.js, Bun, and Deno! And get this: it’s only 3MB gzipped, plus it supports hot extensions like pgvector. As a power user of databases, I have to say: this thing has serious potential.
What Problem Does It Actually Solve?
In traditional frontend development, local storage options are painfully limited:
localStorage: barely functionalIndexedDB: powerful but with an API that feels like punishment- Libraries like Dexie.js or PouchDB: helpful abstractions, but still not SQL
The core issue? No real SQL capability—until now.
pglite gives you a full PostgreSQL instance right in your app. That means you can use familiar SELECT, JOIN, CTE, and even JSONB operations without learning a new query language. Even better, it persists data to IndexedDB (in browsers) or the filesystem (in Node/Bun/Deno), delivering true local-first + real-time responsiveness.
Imagine this: your Electron app, desktop utility, or even PWA now has a real relational database engine—no backend server required. Isn’t that far better than manually juggling Maps and Sets?
Technical Architecture: Hacking PostgreSQL’s “Single-User Mode”
PostgreSQL normally uses a multi-process model—each connection forks a new process. But WASM is single-threaded and can’t fork at all. So how did they pull this off?
The secret lies in PostgreSQL’s single-user mode, originally designed for recovery or initialization. The pglite team repurposed it into an interactive I/O channel that communicates between JavaScript and the WASM module. In short: they squeezed PostgreSQL into a single-threaded sandbox and wrapped it with a friendly TypeScript API.
Yes, this sacrifices multi-connection support (currently single-user only)—but for embedded local scenarios, that’s perfectly fine. After all, you’re probably building a note-taking app or an offline data tool, not a high-concurrency web service.
Getting Started: Hello World in 5 Lines
Installation? One npm command:
bash
npm install @electric-sql/pglite
Then go straight to work:
javascript
import { PGlite } from "@electric-sql/pglite";
const db = new PGlite();
await db.query("select 'Hello world' as message;");
// -> { rows: [ { message: "Hello world" } ] }
This level of simplicity reminded me of my first time using H2 Database for unit tests—lightweight, fast, and dependency-free. And yes, it supports persistence:
- Browser:
new PGlite("idb://my-pgdata") - Node/Bun:
new PGlite("./path/to/pgdata")
Your data survives app restarts! For offline-capable apps (like medical records or field survey tools), this is a game-changer.
Advanced Use Case: Can You Run Vector Search Locally?
The README explicitly mentions support for pgvector—the PostgreSQL extension for AI vector similarity search. That means you can run KNN queries on embeddings directly in the browser!
While the docs don’t provide a full example yet, here’s how it could look:
javascript
const db = new PGlite();
await db.query(`CREATE EXTENSION IF NOT EXISTS vector;`);
await db.query(`
CREATE TABLE items (
id SERIAL PRIMARY KEY,
embedding VECTOR(384)
);
`);
// Insert vectors and query nearest neighbors...
This opens a whole new frontier for frontend AI apps: local vector database + real-time response, with no API latency or privacy concerns.
Caveats and Considerations
Of course, there’s no free lunch:
- Alpha Stage: The project is clearly marked as alpha—use in production at your own risk.
- Single Connection Limit: You can’t have multiple tabs or workers accessing the same DB instance simultaneously (IndexedDB has locking, but logically it’s still single-user).
- Performance Unknown: WASM is fast, but complex queries will inevitably lag behind native PostgreSQL—especially heavy
JOINs or aggregations.
How Would I Use It?
If I were a full-stack developer, I’d leverage pglite to:
- Build offline-first PWAs (e.g., inventory management, field surveys)
- Replace SQLite in Electron apps for full SQL power
- Prototype frontend data logic without spinning up a backend
For Java backends? Not immediately useful—but the concept is inspiring. Could we someday see a GraalVM Native Image version of embedded PostgreSQL?
Is It Worth Learning?
Absolutely. Even if you don’t write TypeScript, understanding how to port a massive C project like PostgreSQL to WASM is a hardcore skill. And as edge computing and local-first architectures gain traction, embedded databases like this will become increasingly vital.
In short, pglite isn’t a toy—it’s a redefinition of where databases can live. It reminds me of a saying: “The best database is the one you never notice.” And now, it’s quietly waiting in your browser, ready to serve.