Skip to content
NewFrom Mongoose to SQL6 min read

PGlite

PGlite is Postgres compiled to WebAssembly, running inside your process with no server, container or port. UQL treats it as Postgres. Use it for tests, where each file gets a fresh database in milliseconds, and for local development on your production dialect.

Terminal window
npm install uql-orm @electric-sql/pglite
import { PgliteQuerierPool } from 'uql-orm/pglite';
export const pool = new PgliteQuerierPool(); // in memory

Pass a directory to keep the data, and PGlite’s own options second. On disk, relaxedDurability stops PGlite from waiting on a flush after every statement inside a transaction; the data is still written:

const pool = new PgliteQuerierPool('file://./pgdata', {
relaxedDurability: true,
});

pgvector is a separate bundle that PGlite loads at startup:

Terminal window
npm install @electric-sql/pglite-pgvector
import { vector } from '@electric-sql/pglite-pgvector';
const pool = new PgliteQuerierPool('memory://', { extensions: { vector } });

Vector search then works as on a server, halfvec and sparsevec included. The extension pins an exact @electric-sql/pglite version, so upgrade both together.

PGlite has a single connection that every querier shares. A transaction holds the whole database, and other queriers wait until it ends. Give work that must run concurrently its own pool, and so its own database; a test suite or a single-user dev session is unaffected.

$lock emits SELECT ... FOR UPDATE, but no second transaction can contend with it, so test row-locking behaviour on a Postgres server. findManyStream pages through a DECLARE/FETCH cursor, inside a transaction of its own if you have none, which blocks the database until the loop ends.

A BYTEA column reads back as a Uint8Array, not a Buffer, so instanceof Buffer fails. A statement binds at most 32,767 values, so UQL splits a large insertMany into smaller chunks. Migration runs hold their lock as a uql/lock record, since queriers share a session.

Otherwise the two are interchangeable: both report the postgres dialect, so migrations and drift:check carry across.