Master Guides

Database

A friendly wrapper over MasterRecord migrations — the dotnet ef of Master.

master db runs the MasterRecord migration CLI inside your backend/ workspace with the right context (AppContext) and environment — so you never juggle paths, and a fresh app needs no setup step before its first migration.

The everyday loop#

terminal
$ # change a model, then:
$ master db new AddPosts # generate a migration from the diff
$ master db migrate # apply pending migrations

A new app ships an InitialCreate migration and its snapshot (since master 2.2.0), so the first master db migrate has something to apply. In a project with no context snapshot, master db new runs enable-migrations for you first — there is no separate “enable” step, exactly like dotnet ef migrations add.

App created before master 2.2.0?
Since masterrecord 1.30.0, migrate applies migration files only, as EF’s database update does. An older scaffold has a User model but no migration, so master db migrate stops and tells you to author the first one: master db new InitialCreate, then master db migrate.

All actions#

CommandWhat it doesEF equivalent
master db migrateApply pending migrations (update-database). Each migration applies atomically.database update
master db new <Name>Create a migration from current models (add-migration).migrations add
master db rollbackRevert the latest migration (update-database-down).database update <prev>
master db statusApplied migrations with timestamps, pending ones, recorded-but-missing files, and the snapshot’s latest migration (migrations-status).migrations list
master db script [-o file]Print (or write) the SQL that migrate would run for pending migrations — nothing is applied (script).migrations script
master db remove [--force]Delete the latest migration file. Refuses an applied migration unless --force, which reverts it first (remove-migration).migrations remove
master db listList migration files (get-migrations).—
master db ensureCreate the database if missing (ensure-database, MySQL/Postgres).database ensure-created
master db enableCreate the context snapshot (enable-migrations). Run automatically when needed.—

Choosing the environment#

--env sets NODE_ENV for the run, which selects backend/config/environments/env.<env>.json. Without it, NODE_ENV is used, falling back to development.

terminal
$ master db --env production migrate # apply to the production database
$ master db migrate --env test # schema for the test database (master test)
$ NODE_ENV=production master db migrate # same thing via the environment

master new generates all three files. SQLite gets a separate file for tests:

backend/config/environments/env.test.json
{
  "AppContext": {
    "type": "better-sqlite3",
    "connection": "db/test/"
  }
}

For MySQL/Postgres the generated files use <app>_development, <app>_test and <app>_production database names — edit host, user and password before the first migration.

Reviewing SQL before it runs#

master db script runs the real migration planner against the live database and captures the statements instead of executing them — DDL plus the tracking-table insert, per migration:

terminal
$ master db script # print to the terminal
$ master db script -o release.sql # write to a file for review / a DBA
$ master db --env production script -o release.sql
release.sql (shape)
-- masterrecord migration script for 'AppContext'
-- generated 2026-08-22T10:15:00.000Z — 1 pending migration(s). This script was NOT applied.
-- Introspection (table/column checks) ran against the live database; statements below are what update-database would execute.

-- Migration: 1755857700000_AddPosts_migration.js
CREATE TABLE IF NOT EXISTS posts (...);
INSERT INTO [_masterrecord_migrations] (migration_name, applied_at) VALUES (?, ?); -- params: ["1755857700000_AddPosts_migration.js","2026-08-22T10:15:00.000Z"]

One statement per line, parameters shown inline as comments; the DDL and quoting follow the engine in your environment file. Migration files are named <timestamp>_<Name>_migration.js.

Inspecting state#

terminal
$ master db status # applied (with timestamps) / pending / missing files / snapshot latest
$ master db list # the migration files on disk
Where things live
The context is AppContext (backend/app/models/AppContext.js); migrations are written to backend/app/models/db/migrations/; the context snapshot (*_contextSnapShot.json) records the model as of the latest authored migration (master db new writes it; migrate never does); credentials live in backend/config/environments/env.<env>.json, keyed by AppContext.
In CI/CD
Run master db --env production migrate as a release step before starting the new version, and master db migrate --env test before master test. See Deployment and Testing.