Migrations
Evolve Inspire schemas through committed migration history, reviewed plans, and a dev loop that stays aligned with that history.
Migrations are the reviewed history of how your database catches up to the schema declared in Inspire.
The schema is the source of truth. You change Inspire, generate a migration plan, review it, and commit the result. You do not hand-author SQL migrations.
What A Migration Is
A migration is a repo-tracked transition between two schema states.
- Inspire declares the target schema
kizaki migrate plancompares current schema to the latest committed snapshot- Kizaki writes a migration directory under
migrations/<NNNN_slug>/ - You review the generated plan before applying and committing
Artifacts
| Artifact | Purpose |
|---|---|
.inspire files | Declares where the schema should end up |
plan.migration | Describes what changed |
snapshot.json | Captures the compiled schema state for historical comparison |
Directory Shape
migrations/
0001_initial/
plan.migration
snapshot.json
0002_add_due_date/
plan.migration
snapshot.jsonExample plan.migration
migration "0002_add_due_date" {
add Task.dueDate: datetime?
add Task.status: TaskStatus = Todo
rename Task.ownerId -> Task.assigneeId
}Development Workflow
kizaki dev And Migration History
kizaki dev keeps local development moving, but committed migrations remain the authority. The dev stack:
- Compares your source schema to the latest committed migration snapshot
- Auto-applies committed pending migrations to the local database
- Fails if your source schema has moved ahead and you have not generated the next migration
$ kizaki dev
Starting local stack...
Applying committed migrations...
0001_initial
0002_add_due_date
Source schema is ahead of committed migration history.
Run `kizaki migrate plan` before continuing.Generating A Migration
Once a schema change stabilizes:
- Edit Inspire
- Iterate locally until the shape is right
- Run
kizaki migrate plan - Review
plan.migration - Run
kizaki migrate apply - Commit the migration directory with the schema change
$ kizaki migrate plan --name add_due_date
Generated migrations/0002_add_due_date/plan.migration
Generated migrations/0002_add_due_date/snapshot.jsonDraft Tip Behavior
If the latest committed migration has not been applied locally, plan rewrites it instead of creating a new numbered migration. If multiple committed migrations are pending, planning fails.
$ kizaki migrate plan
Latest committed migration is still unapplied locally.
Rewriting migrations/0003_rework_tasks/ instead of creating 0004.Commands
kizaki migrate plan
kizaki migrate apply
kizaki migrate dry-run
kizaki migrate statuskizaki migrate plan
Diffs the resolved Inspire workspace against the latest committed snapshot.json. Writes the next migration plan. Surfaces ambiguous cases through [RESOLVE] markers.
$ kizaki migrate plan
Comparing source schema to migrations/0002_add_due_date/snapshot.json...
Generated migrations/0003_split_assignee/plan.migrationkizaki migrate apply
Applies pending committed migrations in order to the local database.
$ kizaki migrate apply
Applying 0003_split_assignee...
Migration applied successfully.kizaki migrate dry-run
Shows generated SQL and impact without executing. Useful before deploys or for destructive/ambiguous changes.
$ kizaki migrate dry-run
Migration: 0003_split_assignee
- rename Task.ownerId -> Task.assigneeId
- add Task.assignedAt: datetime?
No changes applied.kizaki migrate status
Reports the latest committed migration, latest applied migration, and source drift.
$ kizaki migrate status
Latest committed: 0003_split_assignee
Latest applied: 0003_split_assignee
Source drift: noneReviewing plan.migration
Treat the plan as code review material. Check:
- Did the diff detect a rename, or did it drop and re-add?
- Did an additive change stay additive?
- Is a destructive operation intentional?
- Are any
[RESOLVE]markers still present? - Does the plan match the product change you intended?
migration "0004_rework_profile" {
[RESOLVE] rename User.fullName -> User.displayName
add User.avatarUrl: string?
}If [RESOLVE] markers remain, the migration is not ready.
When A Migration Is Required
A migration is required when the database schema changes:
- Adding or removing entities
- Adding, renaming, or removing fields
- Changing indexes or constraints
- Changing enums
No migration needed for runtime-only changes:
- Policy changes
- Route changes
- Auth configuration that does not alter stored schema
- Runtime enforcement behavior
Rule: if Postgres needs to change shape, you need a migration.
Good Migration Hygiene
- One conceptual schema change per migration
- Generate the migration promptly after the change stabilizes
- Review
plan.migrationbefore applying - Commit the migration directory with the schema change
- Avoid letting source drift far ahead of committed history
Zero-Downtime Deploys
The platform applies migrations as part of deploy and coordinates the schema transition with the new application version. Additive changes are straightforward. Renames and drops are staged so old and new app code are not forced through the same query assumptions simultaneously.
Your responsibility remains the same: generate and review the migration carefully.
Related guide: Migrations