An exotically simple database migration tool for node pg.
- Dead simple, zero config!
- Write up and down migrations in the same .sql file!
- Lightweight and easy to integrate into workflows!
npm install --save migratorosaurusYour environment should have a PostgreSQL database setup.
This package requires Node.js >=22.
Use it from your app or migration runner:
import { down, up, validate } from "migratorosaurus";
await validate("postgres://localhost:5432/database", {
directory: `sql/migrations`,
table: "my_migration_history",
});
await up("postgres://localhost:5432/database", {
directory: `sql/migrations`,
table: "my_migration_history",
});
await down("postgres://localhost:5432/database", {
directory: `sql/migrations`,
table: "my_migration_history",
});Migration filenames are enforced and must match:
<YYYYMMDDHHMMSS>_<slug>.sql (for example 20260414153000_create_person.sql).
Files are applied in ascending version order.
<slug>must use lowercase letters, numbers, and underscores only- Non-
.sqlfiles in the directory are ignored - Invalid
.sqlmigration filenames cause startup validation to fail
Each file must contain exactly one up marker and at most one down marker:
-- migrate:up
CREATE TABLE person (
id SERIAL PRIMARY KEY,
name varchar(100) NOT NULL
);
-- migrate:down
DROP TABLE person;The up section must contain SQL. The down marker is optional. If present, its SQL may be empty for irreversible migrations. During rollback, migrations without down SQL execute no SQL but are still removed from the history table, so their up() must be idempotent.
migratorosaurus --helpThe built-in CLI supports:
createcreates a new migration fileupapplies pending migrationsdownrolls back applied migrationsvalidatechecks migration environment and state without applying SQL
The CLI creates filenames in <YYYYMMDDHHMMSS>_<slug>.sql format.
Useful commands:
migratorosaurus create --help
migratorosaurus create --directory sql/migrations --name add_users
migratorosaurus validate --url postgres://localhost:5432/app
migratorosaurus up --url postgres://localhost:5432/app
migratorosaurus down --url postgres://localhost:5432/app --target 20260416090100_add_users.sqlGlobal CLI flags:
--jsonemit machine-readable result JSON tostdout--quietsuppress non-error logs--verbose/-venable debug logs--no-colordisable ANSI color in logs
create command rules:
--nameis required--namemust be a lowercase slug ([a-z0-9][a-z0-9_]*)--directorydefaults toMIGRATION_DIRECTORYor"migrations"--helpand-hare boolean flags- Unknown commands and unknown flags cause the CLI to fail
up / down / validate command rules:
--directorydefaults toMIGRATION_DIRECTORYor"migrations"--directorytakes precedence overMIGRATION_DIRECTORY
validate command behavior:
- validates migration files, order, and applied history consistency
- validates database connectivity and migration table state
- does not create missing migration history tables
- uses the same advisory lock as
up/downand fails fast if another run is active
CLI stream conventions:
- Command results are written to
stdoutonly - Logs (info/warn/error/debug) are written to
stderr - In
--jsonmode,stdoutcontains only structured JSON output - ANSI color in logs is enabled only when
stderris a TTY
The first argument is a required PostgreSQL connection string or pg client configuration.
The second argument is an optional configuration object:
- directory The directory that contains your migration
.sqlfiles. Defaults to"migrations". - quiet Suppress non-error logs.
- verbose Enable debug logs.
- color Enable/disable ANSI color in logs (TTY-aware by default).
- table The name of the database table that stores migration history. Defaults to
"migration_history". Valid values must use conventional PostgreSQL-style names only:table_nameorschema_name.table_name. Table names may only use lowercase letters, numbers, and_, and must start with a letter or_. If you use a schema-qualified name, the schema must already exist. - target An exact migration filename.
By default, up() and down() emit logs to stderr using the same conventions as the CLI.
validate() also logs to stderr and performs checks only (no migration SQL execution).
Use up(config, { target }) to migrate forward until that migration has been applied.
Use down(config) to roll back exactly one migration.
Use down(config, { target }) to roll back newer migrations while leaving the target migration applied.
up() is append-only by version order. If a migration file is added with a version earlier than the latest applied migration after that later migration has already been applied, up() fails instead of silently applying it out of order.
Each migration file runs in its own transaction. If one migration fails, earlier successful migrations stay committed and the failing migration is rolled back. Concurrent runners are serialized with a PostgreSQL advisory lock keyed on the unqualified history table name — migration_history and public.migration_history share the same lock, so runners against same-named tables in different schemas will also serialize. Use distinct table names if that matters.
Clone the repository and install dependencies:
git clone https://github.com/gabts/migratorosaurus
cd migratorosaurus
npm install
npm run build:watchEnsure a PostgreSQL database is running, then run the tests with a DATABASE_URL:
DATABASE_URL="postgres://localhost:5432/database" npm run test