npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pglite-migrate

v1.0.0

Published

Migrate PGlite data across PostgreSQL major versions (e.g. PG17 -> PG18) by transferring data between two PGlite instances, without native binaries or pg_upgrade.

Downloads

596

Readme

pglite-migrate

Migrate PGlite data across PostgreSQL major versions (e.g. PG17 → PG18) — without native binaries or pg_upgrade.

PGlite is PostgreSQL compiled to WASM. Its data directory is a real PostgreSQL cluster, so when PGlite bumps the underlying Postgres major, an existing data directory can no longer be opened by the new engine. Native Postgres fixes this with pg_upgrade, but that needs native server binaries of both majors — which an embedded WASM database doesn't have.

pglite-migrate takes the logical route: it runs two PGlite engines side by side — the old engine on the source data, the new engine on the target — and transfers data between them at the SQL level. The on-disk format never has to be understood. No native binaries, no pg_upgrade.

Why you'd want this

A PG18 PGlite engine physically cannot open a PG17 data directory — that's the failure this library exists to bridge (and the e2e suite proves it on disk). pglite-migrate is the connective tissue for the PGlite, data-directory, cross-major case that the ecosystem doesn't otherwise cover.

  • Genuinely cross-major. The test matrix runs a real PG17 → PG18 migration (PGlite 0.4.x0.5.x), not a same-version round-trip.
  • App-driven or standalone. Let your app create the target schema and just copy the data, or have pglite-migrate reconstruct the app-class schema (tables, columns, sequences, enums, PK/FK/unique/check, indexes) from the source when there's no host app.
  • Fidelity-first transfer. Rows move via PostgreSQL COPY (text format) with a per-table INSERT fallback, preserving json/jsonb, numeric, bytea, arrays and timestamptz exactly. Sequences are realigned with setval so the next inserted id is correct.
  • Handles the hard cases. Foreign keys are topologically ordered so parents load before children, and FK cycles transfer correctly inside a deferred-constraint transaction.
  • Safe by construction. Optional source backup, a dry-run that provably writes nothing, post-migration validation (row-count parity, sequence consistency, or full content digests), idempotent re-runs (error / truncate / skip), and an atomic write-new-then-rename swap primitive.

Install

npm install pglite-migrate @electric-sql/pglite

@electric-sql/pglite is a peer dependency — your app supplies the engine version(s). To open two majors at once, install both under npm aliases:

npm install pglite-old@npm:@electric-sql/[email protected]   # PG17
npm install pglite-new@npm:@electric-sql/[email protected]   # PG18

Quick start (library, app-driven)

The recommended path. Your app already knows how to create its own schema, so let it: create the schema on the new engine, then transfer the data.

import { migrate } from 'pglite-migrate';
import { PGlite as PGliteOld } from 'pglite-old'; // npm alias of the old version (PG17)
import { PGlite as PGliteNew } from 'pglite-new'; // npm alias of the new version (PG18)

const source = new PGliteOld('/path/to/old-data');
const target = new PGliteNew('/path/to/new-data');
await createSchema(target);        // your app's normal startup migrations

const report = await migrate({ source, target });   // validates row counts by default
console.log(`${report.totalRows} rows across ${report.tables.length} tables`);

No host app? Let pglite-migrate rebuild the schema from the source first:

const report = await migrate({ source, target, reconstructSchema: true });
// Out-of-scope objects (views, triggers, functions, RLS, partitioning) are
// reported in report.reconstruction.unsupported, never silently dropped.

The core never imports @electric-sql/pglite directly — it speaks to a minimal PGliteLike interface, which is exactly what lets you hand it two different majors at once.

CLI

pglite-migrate <source-data-dir> <target-data-dir> [options]

| Option | Description | | --- | --- | | --source-engine <pkg> / --target-engine <pkg> | npm module/alias for each engine (default @electric-sql/pglite) | | --validate <level> | Post-migration check: off | counts | full (default counts) | | --on-existing <mode> | Non-empty target: error | truncate | skip (default error) | | --reconstruct-schema | Rebuild the source's app-class schema on an empty target first | | --dry-run | Report the plan without writing anything | | --backup / --backup-dir <path> | Back up the source data dir before migrating |

Demos

Animated terminal captures of the real CLI against a live PG17 → PG18 pair. Each clip opens with a title card for the concept, then types the command and reveals its verbatim output. Regenerate them any time with npm run demo.

Scope

In scope — app-class schemas: tables, columns (including generated/identity), sequences, enums, primary/foreign/unique/check constraints, and indexes; data fidelity for the common types.

Out of scope — full pg_dump parity: views, materialized views, triggers, functions, RLS policies, and partitioning. During standalone reconstruction these are detected and reported, never silently dropped.

How it compares

| Need | Tool | | --- | --- | | Migrate a native Postgres cluster, files in place | pg_upgrade (+ portable binaries via embedded-postgres / zonkyio/embedded-postgres-binaries) | | Pure-JS schema introspection | pg-introspection | | Pure-JS schema dump (DDL) | pg-schema-dump | | Migrate PGlite data across a major version | this package |

Documentation

Full requirements and design specs live in docs/ (numbered for linear reading). Start with docs/1-overview.md and docs/ARCHITECTURE.md; the per-feature specs (COPY-text transfer, FK cycles, standalone reconstruction, backup, atomic swap, dry-run, validation, idempotence) are docs 7–14.

License

MIT