You need Node 22.13 or later (Node 24 LTS recommended), Git and a terminal. Nothing else to install.
Checking your Node version
Run node --version. If it prints something older than v22.13.0, install the current LTS from nodejs.org or with your version manager.
The sample uses the SQLite database built into Node, so there are no packages to install and no database server to run. Some Node versions print an ExperimentalWarning about SQLite the first time; it's harmless.
Get the sample
git clone https://github.com/computesphere-samples/learn.git cd learn/labs/migrations ls migrationsCloned
learnalready in lesson 2.2.4? Don't clone again:cdinto thatlearnfolder, rungit pullto fetch the latest, thencd labs/migrations.You should seeTwo migrations, each with an up and a down file.
Check what has run
node migrate.js statusThis creates the database, a local file called
app.db, and theschema_migrationstable that records what has run.You should see[ ] 001_create_tasks and [ ] 002_add_due_date: nothing has run yet.
Read one migration
cat migrations/002_add_due_date.up.sql migrations/002_add_due_date.down.sqlOn Windows, open the two files in your editor instead.
You should seeThe up adds a due_date column to tasks; the down drops it.
Apply them
node migrate.js upThey run in order, because 002 changes the table that 001 creates.
You should seeApplied 001_create_tasks, then Applied 002_add_due_date.
See the schema
node migrate.js schemaSQLite has no separate true-or-false or date types, so
doneis stored as anINTEGER(0 or 1) anddue_dateasTEXT.Check yourself
You should seeA table of four columns: id, title, done and due_date.
Roll back the last one
node migrate.js down node migrate.js schema node migrate.js statusDown undoes only the most recent migration. Any dates in
due_datewould be gone now.You should seeRolled back 002_add_due_date. schema shows three columns; status shows [x] 001_create_tasks and [ ] 002_add_due_date.
Apply it again
node migrate.js up node migrate.js schemaTo start over at any point, delete
app.db.You should seeApplied 002_add_due_date, and due_date is back in schema.
What the runner does
migrate.js is about 50 lines. On up it lists the *.up.sql files in order, skips the versions already in schema_migrations, and runs each new one in a transaction together with the insert that records it. If the SQL fails, both roll back, so the record never claims a change that didn't happen.
Real migration tools add locking, so two copies can't run at once, and checksums that catch an edited migration. The idea is the same.