Peter Amiri
06/16/2026, 4:22 PMcreateTable returns a builder — nothing runs until you call .create() (or .change() for changeTable). The #1 silent footgun.
• The column helpers all speak columnNames (plural, comma-list to add several at once). primaryKey() is the one exception — it does NOT split on commas.
• timestamps() adds THREE columns: createdAt, updatedAt, AND deletedAt (the soft-delete marker). Don't hand-roll them.
• execute() takes only sql — no parameter binding. Inline SQL + NOW() for portable dates; `addRecord()`/`updateRecord()` when you need binding.
• Each migration runs in its own transaction; a failure stops the loop and leaves you consistent.
• The team part: migrate info flags orphan rows [?], migrate doctor gives a health report, and `forget`/`pretend --yes` reconcile a shared DB without rolling back the wrong way.
Shared-DB reconciliation has its own deep dive in the 4.0.2 release notes — this post is the get-started-and-stay-out-of-trouble version.