WASM Databases
WASM (WebAssembly) databases expand browser client-side storage options beyond the traditional options such as IndexedDB. IndexedDB provides a key-value API rather than a relational model. There have been attempts previously at client side storage with SQL syntax in browsers, such as WebSQL, which was removed from Chrome in 2022.
With WebAssembly, database engines can run directly inside the browser runtime. SQLite compiled to WASM (Sqlite3 WASM) and PGlite are the two examples of this.
Last year, Notion added a WASM implementation of SQLite to their website for caching data, which improved page load times by 20%.
PGlite brings PostgreSQL to the browser using WebAssembly. From the PGlite documentation:
PGlite is a WASM Postgres build packaged into a TypeScript/JavaScript client library, that enables you to run Postgres in the browser, Node.js and Bun, with no need to install any other dependencies. It’s under 3mb Gzipped, and has support for many Postgres extensions, including pgvector.
Supabase has a PGlite based demo at database.build, which uses IndexedDB for local persistence.
Compared to IndexedDB, these WASM databases expose a relational model with SQL queries and transactions. In the case of PGlite, this includes PostgreSQL compatible features such as extensions and listen/notify. Extensions such as pgvector enable advanced use cases like vector similarity search directly in the browser.
For persistence, these databases rely on browser-backed storage such as IndexedDB or the File System Access API (OPFS). There are some limitations around concurrency, for example PGlite runs in a single connection mode only.
Try PGlite in your browser
You can try out PGlite in your browser console:
- Load the browser bundle
const { PGlite } = await import(
"https://cdn.jsdelivr.net/npm/@electric-sql/pglite/dist/index.js"
);- Initialize in-memory (no persistence). Data will be wiped on page refresh
const db = new PGlite();- Create a table
await db.query(`
CREATE TABLE tasks (
id SERIAL PRIMARY KEY,
title TEXT NOT NULL,
completed BOOLEAN DEFAULT FALSE
);
`);- Add some data
await db.query(
`
INSERT INTO tasks (title) VALUES
($1),
($2);
`,
[
"Explore PGlite Extensions",
"Try vector similarity search with pgvector and PGlite",
],
);- Query and display
const res = await db.query("SELECT * FROM tasks;");
console.table(res.rows);