Skip to main content

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.go to use your real module import path;
  • .queen.yaml or 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"