Database & migrations
The starter treats schema changes as first-class code: each migration is a Go file registered in a central list, with status, rollback, and create helpers exposed through CLI flags and Makefile targets.
Why not only AutoMigrate?
AutoMigrate is convenient in demos but weak for production:
- Hard to review schema diffs in pull requests.
- Hard to rollback precisely when a deploy goes wrong.
- Teams lose a chronological history tied to application releases.
Numbered migration files give you an audit trail similar to frameworks you may know from other languages.
File layout
| Path | Meaning |
|---|---|
database/migrations/*.go | One logical change per file (or tightly related changes). |
database/migration.go | Registers available migrations with the runner. |
database/manager.go | User-facing operations: run, rollback, status, scaffold new file. |
database/entities/*.go | GORM models representing tables. |
Keep migration order compatible with existing data — avoid destructive operations without a follow-up data migration plan.
Running migrations
Apply all pending
go run cmd/main.go --migrate:run
Equivalent shorthand may exist as --migrate depending on parser in script/command.go — check the file for exact spellings.
Inspect status
go run cmd/main.go --migrate:status
Use this when CI complains or when you suspect partial application.
Roll back
Rollback one batch (optional batch count):
go run cmd/main.go --migrate:rollback 1
Rollback everything tracked (dangerous in production — use only in dev or with backups):
go run cmd/main.go --migrate:rollback:all
Scaffold a new migration
go run cmd/main.go --migrate:create:add_user_preferences
Open the generated file, implement Up / Down (or the interfaces your manager expects), then register it in database/migration.go if the generator does not do so automatically.
Entities and migrations — stay aligned
When you add a column:
- Migration adds/alters the column at the database level.
- Entity struct gains the field with correct GORM tags.
- DTOs expose the field to HTTP where appropriate.
- Repositories read/write the new field.
Skipping step 1 causes runtime errors; skipping step 2 causes silent omission of data in ORM operations.
PostgreSQL extensions
The starter may attempt to ensure uuid-ossp (see RunExtension in database config). On managed databases you might need elevated privileges or a provider-specific UUID type — adjust for your host’s rules.
Seeding
go run cmd/main.go --seed
Seeding is not automatically idempotent unless you wrote it that way (ON CONFLICT, FirstOrCreate, etc.). Treat production seed with extreme care — prefer dedicated admin tools or one-off jobs.
Backup and restore (operations)
This template does not automate backups. For real systems:
- Schedule logical dumps (
pg_dump) or disk snapshots. - Test restore quarterly.
Document your organisation’s RPO/RTO targets separately.
Troubleshooting
| Symptom | Likely cause |
|---|---|
relation does not exist | Migration not applied on that database. |
column X does not exist | Code ahead of migrations or wrong DB targeted. |
| Rollback errors | Down migration missing or not inverse of Up. |
Capture --migrate:status output when asking for help — it tells readers which version the database believes it is on.