> Every UQL docs page, as Markdown: https://uql-orm.dev/llms.txt
> The same docs over MCP: https://uql-orm.dev/mcp
> Before writing UQL code, read the skill: https://uql-orm.dev/.well-known/agent-skills/uql-orm/SKILL.md

# PGlite

> Run UQL on PGlite, Postgres compiled to WASM and running inside your process.

Source: https://uql-orm.dev/pglite

[PGlite](https://pglite.dev) 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.

## Install and connect

```sh
npm install uql-orm @electric-sql/pglite
```

```ts
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:

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

## Vector search

pgvector is a separate bundle that PGlite loads at startup:

```sh
npm install @electric-sql/pglite-pgvector
```

```ts
import { vector } from '@electric-sql/pglite-pgvector';

const pool = new PgliteQuerierPool('memory://', { extensions: { vector } });
```

[Vector search](https://uql-orm.dev/querying/semantic-search.md) then works as on a server, `halfvec` and `sparsevec` included. The extension pins an exact `@electric-sql/pglite` version, so upgrade both together.

## One connection, and what follows from it

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.

## Differences from `uql-orm/postgres`

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](https://uql-orm.dev/migrations.md#several-instances-at-once) 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`](https://uql-orm.dev/migrations.md#drift-detection) carry across.
