Migrations
The API uses Goose for database migrations. Migration files live in internal/db/migrations/ and are embedded into the binary — migrations run automatically on startup.
File naming
Migration files follow the Goose timestamp convention:
Each file contains an Up and Down block:
-- +goose Up
-- +goose StatementBegin
CREATE TABLE ...;
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP TABLE ...;
-- +goose StatementEnd
Creating a migration
Generate a new migration file (requires goose installed):
This creates a timestamped file in internal/database/migrations/. Write your Up and Down SQL, then commit the file.
Warning
Never modify an existing migration file. If you need to alter a table, create a new migration.
Running migrations
Migrations run automatically when the API starts. To run them manually from the host:
This uses DATABASE_URL_MIGRATION (pointing to localhost:5432) rather than DATABASE_URL (the Docker-internal hostname), so it works when run outside the container.
Rolling back
To roll back the last migration:
SQLC regeneration
After modifying a migration or a query file in internal/database/queries/, regenerate the Go code:
This updates internal/database/sqlc/ — never edit that directory manually. See sqlc.yml for the full codegen configuration.