Workflows
This page shows how the pieces fit together in real projects.
New project
go get github.com/yaop-labs/queen
go run ./cmd/migrate init --driver postgres --with-config
go mod tidy
Then edit:
cmd/migrate/main.goto use your real module import path;.queen.yamlor your deploy flags;- generated migration files under
migrations/.
Daily development
Create a migration:
go run ./cmd/migrate create add_user_slug --type sql
Register or review the generated migration, then inspect the plan:
go run ./cmd/migrate validate --driver postgres --dsn "$DATABASE_URL"
go run ./cmd/migrate plan --driver postgres --dsn "$DATABASE_URL"
go run ./cmd/migrate up --driver postgres --dsn "$DATABASE_URL"
If the migration contains Go code, set ManualChecksum and bump it when the function changes.
CI gate
Use check as the compact CI entrypoint:
go run ./cmd/migrate check \
--driver postgres \
--dsn "$DATABASE_URL" \
--ci \
--no-gaps
For an empty disposable test database:
go run ./cmd/migrate check \
--driver postgres \
--dsn "$TEST_DATABASE_URL" \
--rollback-test
Production deploy
Build the migrator once:
go build -o migrate ./cmd/migrate
Run preflight checks:
./migrate check --driver postgres --dsn "$DATABASE_URL" --ci --no-gaps
./migrate plan --driver postgres --dsn "$DATABASE_URL"
Apply:
./migrate up --driver postgres --dsn "$DATABASE_URL" --yes
./migrate status --driver postgres --dsn "$DATABASE_URL"
For .queen.yaml production environments:
./migrate up --use-config --env production --unlock-production --yes
Keep one intentional migrator job active per environment.
Existing database
If the database schema already exists and you want Queen to start tracking it:
go run ./cmd/migrate baseline --at 010 --dry-run --driver postgres --dsn "$DATABASE_URL"
go run ./cmd/migrate baseline --at 010 --driver postgres --dsn "$DATABASE_URL"
Baseline records migrations as applied without executing SQL. Use it only after checking that the schema actually matches those migrations.
Import from goose
Preview first:
go run ./cmd/migrate import ./db/migrations --from goose --output migrations --dry-run
Then import:
go run ./cmd/migrate import ./db/migrations --from goose --output migrations
The importer fails instead of overwriting existing files. Review generated Go files before committing.
Clean up old migration history
Squash registered SQL migrations:
go run ./cmd/migrate squash 001,002,003 --into initial_schema --dry-run --driver postgres --dsn "$DATABASE_URL"
go run ./cmd/migrate squash 001,002,003 --into initial_schema --driver postgres --dsn "$DATABASE_URL"
Commit the generated migration after review. Do not delete old migrations from a live project until your release process accounts for databases that may still need them.
Investigate a production issue
Start with non-mutating commands:
go run ./cmd/migrate status --driver postgres --dsn "$DATABASE_URL"
go run ./cmd/migrate doctor --driver postgres --dsn "$DATABASE_URL"
go run ./cmd/migrate gap detect --driver postgres --dsn "$DATABASE_URL"
go run ./cmd/migrate explain 010 --driver postgres --dsn "$DATABASE_URL"
For local inspection, use the TUI:
go run ./cmd/migrate tui --driver postgres --dsn "$DATABASE_URL"
For a live migration that needs SQL visibility:
go run ./cmd/migrate up --tap --driver postgres --dsn "$DATABASE_URL"