β

ObjectQL v4.0 is currently in Beta.

ObjectStack LogoObjectQL
Drivers

PG WASM Driver

Full PostgreSQL in the browser via PGlite WASM with IndexedDB, OPFS, and in-memory storage

PG WASM Driver

The PG WASM Driver (@objectql/driver-pg-wasm) embeds a complete PostgreSQL instance inside the browser using PGlite — a WASM build of Postgres. It supports JSONB, full-text search, transactions, and array fields with no server required.

Features

  • Full PostgreSQL: Real Postgres query engine compiled to WebAssembly
  • Multiple Storage Backends: IndexedDB, OPFS, or in-memory
  • Transactions: Full ACID transaction support with begin/commit/rollback
  • JSONB: Native JSON document queries
  • Full-Text Search: Built-in tsvector / tsquery support
  • Array Fields: Native PostgreSQL array column types
  • Knex Pipeline: Reuses @objectql/driver-sql Knex codegen (client: 'pg')
  • Extensions: Load PGlite extensions (e.g., pgvector)

Architecture

QueryAST → Knex (client: 'pg') → SQL string → PGlite WASM → IndexedDB / OPFS / Memory

The driver compiles queries through the same Knex pg pipeline used by the server-side SQL driver, then executes the SQL against a PGlite WASM instance. The result is full PostgreSQL semantics — including window functions, CTEs, and JSONB operators — running entirely client-side.

Installation

pnpm add @objectql/driver-pg-wasm

Configuration

interface PgWasmDriverConfig {
  /** Storage backend */
  storage: 'idb' | 'opfs' | 'memory';
  /** Database name (IndexedDB database or OPFS directory). Default: 'objectql' */
  database?: string;
  /** PGlite extensions to load */
  extensions?: Record<string, unknown>;
}
OptionTypeDefaultDescription
storage'idb' | 'opfs' | 'memory''idb'Persistence backend
databasestring'objectql'Database / namespace identifier
extensionsRecord<string, unknown>{}PGlite extensions to load

Quick Start

import { ObjectStackKernel } from '@objectstack/runtime';
import { PgWasmDriver } from '@objectql/driver-pg-wasm';

const kernel = new ObjectStackKernel([
  new PgWasmDriver({
    storage: 'idb',
    database: 'my-app'
  })
]);

await kernel.start();

Storage Backends

BackendPersistenceCapacityBest For
idb (IndexedDB)✅ PersistentHundreds of MB (quota-dependent)Default — widest browser support
opfs (Origin Private File System)✅ PersistentGB-scaleLarge datasets, near-native I/O
memory❌ EphemeralWASM heap onlyUnit tests, SSR, throwaway sessions
// IndexedDB (default, broadest support)
new PgWasmDriver({ storage: 'idb' });

// OPFS (best performance for large datasets)
new PgWasmDriver({ storage: 'opfs' });

// Memory (testing)
new PgWasmDriver({ storage: 'memory' });

PostgreSQL-Specific Features

JSONB Queries

const ctx = kernel.createContext({ isSystem: true });
const settings = ctx.object('settings');

// Create a record with JSONB data
await settings.create({
  userId: 'user-1',
  preferences: { theme: 'dark', locale: 'en', notifications: true }
});

// Query nested JSONB fields
const darkThemeUsers = await settings.find({
  filters: [['preferences.theme', '=', 'dark']]
});
const articles = ctx.object('articles');

// Full-text search using PostgreSQL tsvector
const results = await articles.find({
  filters: [['content', 'contains', 'ObjectQL migration guide']]
});

Transactions

const driver = kernel.getDriver();
const trx = await driver.beginTransaction();

try {
  await driver.create('orders', { total: 99.99, status: 'pending' }, { transaction: trx });
  await driver.update('inventory', 'item-1', { stock: 49 }, { transaction: trx });
  await driver.commit(trx);
} catch (error) {
  await driver.rollback(trx);
  throw error;
}

Extensions

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

const driver = new PgWasmDriver({
  storage: 'idb',
  extensions: { vector }
});

Browser Requirements

RequirementFallback
WebAssemblyRequired — no fallback
IndexedDBRequired for idb storage
OPFSRequired for opfs storage; needs Cross-Origin-Isolated headers
SharedArrayBufferRequired for OPFS sync access

For OPFS storage, set these HTTP headers:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

Capabilities

{
  transactions: true,
  joins: true,
  aggregations: true,
  fullTextSearch: true,
  jsonFields: true,
  arrayFields: true,
  queryFilters: true,
  querySorting: true,
  queryPagination: true,
  bulkOperations: true,
  schemaSync: true
}

Usage

const ctx = kernel.createContext({ isSystem: true });
const projects = ctx.object('projects');

// Create
const project = await projects.create({
  name: 'ObjectQL v5',
  tags: ['typescript', 'wasm'],
  metadata: { priority: 'high', milestone: 'Q3' }
});

// Query with filters, sort, and pagination
const active = await projects.find({
  filters: [['metadata.priority', '=', 'high']],
  sort: [['created_at', 'desc']],
  limit: 20
});

// Aggregations
const stats = await projects.aggregate({
  aggregations: [
    { function: 'count', field: '*', alias: 'total' }
  ],
  groupBy: ['status']
});

Bundle Size

ComponentSize (gzip)
PGlite WASM binary~2.8 MB
Driver + Knex pg codegen~200 KB
Total~3 MB

Consider lazy-loading the driver to keep initial bundle size small:

const { PgWasmDriver } = await import('@objectql/driver-pg-wasm');

On this page