Versioned migrations
Use versioned migrations when a database change must be reviewed before it runs, replayed across environments, and visible in deployment history. Each change becomes an ordered pair of SQL files that Ptah hashes, validates, applies, and records in the database.
You may write those files yourself or let Ptah derive them from a desired schema. That choice changes only how the files originate; the review and execution lifecycle is the same.
Treat migration files as code. They live in your repository, they are covered by an integrity file, and they go through review before they reach a shared database.
Where the files come from
Section titled “Where the files come from”Two ways, and the lifecycle after them is the same. Only the first step differs,
so a project that never describes a desired schema uses every verb below except
plan and generate.
You write them
Section titled “You write them”ptah migrations create add_orders --migrations-dir ./migrations# write the SQL in the generated *.up.sql and *.down.sqlcreate scaffolds the pair and leaves their contents to you. Nothing here reads
a schema source, and nothing later asks for one.
Ptah derives them from a desired schema
Section titled “Ptah derives them from a desired schema”ptah migrations plan \ --schema-file schema.sql \ --db-url "$DATABASE_URL"
ptah migrations generate \ --schema-file schema.sql \ --db-url "$DATABASE_URL" \ --migrations-dir ./migrationsplan previews the SQL for the difference between the desired schema and the
database; generate writes that difference as the same pair of files.
The lifecycle both share
Section titled “The lifecycle both share”ptah migrations hash --dir ./migrationsptah migrations validate --dir ./migrations
ptah migrations up \ --db-url "$DATABASE_URL" \ --migrations-dir ./migrations \ --verify-sumSeal the directory, check it against its own integrity file, and apply what is pending. Each step is covered in depth on its own page:
| Task | Page |
|---|---|
| Write a migration by hand, or plan and write one from schema differences | Generate migrations |
| Apply pending migrations and inspect state | Apply migrations |
| Roll back to an earlier version | Roll back migrations |
| Hash the directory, validate it, and assert preconditions | Integrity and safety |
| Lint the SQL and gate destructive changes | Lint and gate unsafe SQL |
| Edit, reorder, delete, or repair migrations | Maintain migration history |
| Adopt an existing golang-migrate, Goose, Flyway, or Liquibase directory | Import from another tool |
| Squash long history into a bootstrap snapshot | Checkpoints |
| Reconcile reference/lookup rows declaratively | Reference data |
The migration directory
Section titled “The migration directory”A migration directory holds one *.up.sql/*.down.sql pair per version plus
the ptah.sum integrity file, and each target database records its applied
versions in a revision table (schema_migrations by default). Pending work
is the set of directory versions not yet in that table. The full model —
file layout, version ordering, integrity files, checkpoint markers, and the
native and Atlas directory formats — is on
The migration directory.
Atlas-compatible command paths for the same lifecycle live in the separate
ptah-compat drop-in binary:
ptah-compat migrate hash --dir ./migrationsptah-compat migrate apply --url "$DATABASE_URL" --dir ./migrationsNext steps
Section titled “Next steps”- Producing your first migration files? Generate migrations.
- Starting from a database or migration history built outside Ptah? Adopt an existing database.
- Still deciding between versioned files and direct applies? Choose a workflow.