Down migrations, inferred
Leave out down and reversible operations undo themselves: createTable becomes DROP TABLE.
Automatic down migrations
Write migrations in JavaScript, TypeScript or SQL, preview the exact SQL, and roll back without writing every down migration by hand.
npm add pg && npm add -D node-pg-migrateLeave out down and reversible operations undo themselves: createTable becomes DROP TABLE.
Automatic down migrations
up --dry-run prints the SQL a real run would execute, inside a read-only transaction that cannot change your data.
Dry runs
Pending migrations run in a single transaction under an advisory lock, and an order check refuses migrations that arrive out of sequence.
Run options
Scaffold migrations as .js, .ts or plain .sql files with create, and write them against a fully typed pgm API.
TypeScript setup
Tables and indexes, but also functions, triggers, policies, roles, domains and casts, each with its own operations.
Browse operations
Run up, down and redo from the terminal, or import runner() and migrate from a script, a test suite or your server.
Programmatic API
Write migrations in TypeScript, JavaScript or plain SQL. In TypeScript and JavaScript every pgm call compiles to SQL: the second panel is exactly what node-pg-migrate up --pretty runs, plus the down it infers because the migration leaves one out. Hover the TypeScript code to see its types.
import type { MigrationBuilder } from 'node-pg-migrate';
export async function up(pgm: MigrationBuilder): Promise<void> {
pgm.createTable('users', {
id: 'id',
email: { type: 'text', notNull: true, unique: true },
createdAt: {
type: 'timestamptz',
notNull: true,
default: pgm.func('now()'),
},
});
pgm.createIndex('users', 'createdAt');
}export const up = (pgm) => {
pgm.createTable('users', {
id: 'id',
email: { type: 'text', notNull: true, unique: true },
createdAt: {
type: 'timestamptz',
notNull: true,
default: pgm.func('now()'),
},
});
pgm.createIndex('users', 'createdAt');
};-- Up Migration
CREATE TABLE "users" (
"id" serial PRIMARY KEY,
"email" text UNIQUE NOT NULL,
"createdAt" timestamptz DEFAULT now() NOT NULL
);
CREATE INDEX "users_createdAt_index" ON "users" ("createdAt");
-- Down Migration
DROP INDEX "users_createdAt_index";
DROP TABLE "users";CREATE TABLE "users" (
"id" serial PRIMARY KEY,
"email" text UNIQUE NOT NULL,
"createdAt" timestamptz DEFAULT now() NOT NULL
);
CREATE INDEX "users_createdAt_index" ON "users" ("createdAt");DROP INDEX "users_createdAt_index";
DROP TABLE "users";node-pg-migrate only targets PostgreSQL, so it can cover what Postgres actually has. Each of these has its own operations in the pgm API: