PGlite is a WASM Postgres build packaged into a TypeScript client library that enables you to run Postgres in the browser, Node.js and Bun, with no need to install any other dependencies. It is only 3.7mb gzipped.
PGlite - the WASM build of Postgres from ElectricSQL.
Build reactive, realtime, local-first apps directly on Postgres.
PGlite - Postgres in WASM
PGlite is a WASM Postgres build packaged into a TypeScript client library that enables you to run Postgres in the browser, Node.js and Bun, with no need to install any other dependencies. It is only 2.6mb gzipped.
It can be used as an ephemeral in-memory database, or with persistence either to the file system (Node/Bun) or indexedDB (Browser).
Unlike previous "Postgres in the browser" projects, PGlite does not use a Linux virtual machine - it is simply Postgres in WASM.
It is being developed at ElectricSQL in collaboration with Neon. We will continue to build on this experiment with the aim of creating a fully capable lightweight WASM Postgres with support for extensions such as pgvector.
Whats new in V0.1
Version 0.1 (up from 0.0.2) includes significant changes to the Postgres build - it's about 1/3 smaller at 2.6mb gzipped, and up to 2-3 times faster. We have also found a way to statically compile Postgres extensions into the build - the first of these is pl/pgsql with more coming soon.
Fix for missing pg_catalog and information_schema tables and view #41
We have also published some benchmarks in comparison to a WASM SQLite build, and both native Postgres and SQLite. While PGlite is currently a little slower than WASM SQLite we have plans for further optimisations, including OPFS support and removing some the the Emscripten options that can add overhead.
Browser
It can be installed and imported using your usual package manager:
await pg.query(
'INSERT INTO test (name) VALUES ($1);',
[ 'test' ]
);
// { affectedRows: 1 },
QueryOptions:
The query and exec methods take an optional options objects with the following parameters:
rowMode: "object" | "array"
The returned row object type, either an object of felidName: value mappings or an array of positional values. Defaults to "object".
parsers: ParserOptions
An object of type {[[pgType: number]: (value: string) => any;]} mapping Postgres data type id to parser function.
For convenance the pglite package exports a const for most common Postgres types:
import { types } from"@electric-sql/pglite";
await pg.query(`
SELECT * FROM test WHERE name = $1;
`, ["test"], {
rowMode: "array",
parsers: {
[types.TEXT]: (value) => value.toUpperCase(),
}
});
To start an interactive transaction pass a callback to the transaction method. It is passed a Transaction object which can be used to perform operations within the transaction.
Transaction objects:
tx.query<T>(query: string, params?: any[], options?: QueryOptions): Promise<Results<T>>
The same as the main .query method.
tx.exec(query: string, options?: QueryOptions): Promise<Array<Results>>
The same as the main .exec method.
tx.rollback()
Rollback and close the current transaction.
Example:
await pg.transaction(async (tx) => {
await tx.query(
'INSERT INTO test (name) VALUES ('$1');',
[ 'test' ]
);
returnawait ts.query('SELECT * FROM test;');
});
.close(): Promise<void>
Close the database, ensuring it is shut down cleanly.
Properties:
.readyboolean (read only): Whether the database is ready to accept queries.
.closedboolean (read only): Whether the database is closed and no longer accepting queries.
.waitReadyPromise: Promise that resolves when the database is ready to use. Note that queries will wait for this if called before the database has fully initialised, and so it's not necessary to wait for it explicitly.
Results Objects:
Result objects have the following properties:
rows: Row<T>[] - The rows retuned by the query
affectedRows?: number - Count of the rows affected by the query. Note this is not the count of rows returned, it is the number or rows in the database changed by the query.
fields: { name: string; dataTypeID: number }[] - Field name and Postgres data type ID for each field returned.
Row Objects:
Rows objects are a key / value mapping for each row returned by the query.
The .query<T>() method can take a TypeScript type describing the expected shape of the returned rows. (Note: this is not validated at run time, the result only cast to the provided type)
Web Workers:
It's likely that you will want to run PGlite in a Web Worker so that it doesn't block the main thread. To aid in this we provide a PGliteWorker with the same API as the core PGlite but it runs Postgres in a dedicated Web Worker. To use, import from the /worker export:
import { PGliteWorker } from"@electric-sql/pglite/worker";
const pg = newPGliteWorker('idb://my-database');
await pg.exec(`
CREATE TABLE IF NOT EXISTS test (
id SERIAL PRIMARY KEY,
name TEXT
);
`);
Work in progress: We plan to expand this API to allow sharing of the worker PGlite across browser tabs.
Extensions
PGlite supports the pl/pgsql procedural langue extension, this is included and enabled by default.
In future we plan to support additional extensions, see the roadmap.
How it works
PostgreSQL typically operates using a process forking model; whenever a client initiates a connection, a new process is forked to manage that connection. However, programs compiled with Emscripten - a C to WebAssembly (WASM) compiler - cannot fork new processes, and operates strictly in a single-process mode. As a result, PostgreSQL cannot be directly compiled to WASM for conventional operation.
Fortunately, PostgreSQL includes a "single user mode" primarily intended for command-line usage during bootstrapping and recovery procedures. Building upon this capability, PGlite introduces a input/output pathway that facilitates interaction with PostgreSQL when it is compiled to WASM within a JavaScript environment.
Limitations
PGlite is single user/connection.
Roadmap
PGlite is Alpha and under active development, the current roadmap is:
/packages/pglite
The TypeScript package for PGlite
/postgres(git submodule)
A fork of Postgres with changes to enable compiling to WASM:
/electric-sql/postgres-wasm
Please use the issues in this main repository for filing issues related to either part of PGlite. Changes that affect both the TypeScript package and the Postgres source should be filed as two pull requests - one for each repository, and they should reference each other.
PGlite is a WASM Postgres build packaged into a TypeScript client library that enables you to run Postgres in the browser, Node.js and Bun, with no need to install any other dependencies. It is only 3.7mb gzipped.
The npm package @electric-sql/pglite receives a total of 260,558 weekly downloads. As such, @electric-sql/pglite popularity was classified as popular.
We found that @electric-sql/pglite demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.It has 3 open source maintainers collaborating on the project.
Package last updated on 28 Mar 2024
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
A Stanford study reveals 9.5% of engineers contribute almost nothing, costing tech $90B annually, with remote work fueling the rise of "ghost engineers."