Auto-generate Postgres migration files from Go structs.
No ORM required. Works with any raw SQL setup (pgx, sqlx, database/sql).
Go struct changes → gomigrate detects diff → generates .up.sql + .down.sql
go install github.com/basant-rai/gomigrate/cmd/gomigrate@latestm := migrator.New(db, "migrations")
m.Register(&User{}, "users")
m.Register(&Card{}, "card_relationships")
m.Register(&FuelTransaction{}, "fuel_transactions")export DATABASE_URL="postgresql://<USERNAME>:<PASSWORD>@<HOST>:<PORT>/<DB_NAME>"
gomigrate --diffOutput:
⚠️ Detected 2 change(s):
+ ADD [users] profile_pic TEXT
+ ADD [users] avatar_url TEXT
gomigrate --generate add_profile_pic_to_usersOutput:
✅ Generated migration files:
migrations/000006_add_profile_pic_to_users.up.sql
migrations/000006_add_profile_pic_to_users.down.sql
Run: make migrate-up
make migrate-up000006_add_profile_pic_to_users.up.sql:
-- Auto-generated by gomigrate
-- Generated at: 2024-01-15 10:30:00
-- Alter table: users
ALTER TABLE users ADD COLUMN IF NOT EXISTS profile_pic TEXT NOT NULL DEFAULT '';
ALTER TABLE users ADD COLUMN IF NOT EXISTS avatar_url TEXT NOT NULL DEFAULT '';
SELECT '✅ 000006_add_profile_pic_to_users applied' AS status;000006_add_profile_pic_to_users.down.sql:
-- Auto-generated by gomigrate
-- Generated at: 2024-01-15 10:30:00
-- Revert table: users
ALTER TABLE users DROP COLUMN IF EXISTS profile_pic;
ALTER TABLE users DROP COLUMN IF EXISTS avatar_url;
SELECT '✅ 000006_add_profile_pic_to_users rolled back' AS status;gomigrate reads db tags from your structs:
type User struct {
domain.Base // id, created_at, updated_at (skipped)
Name string `db:"name"` // TEXT NOT NULL DEFAULT ''
Age int64 `db:"age"` // BIGINT NOT NULL DEFAULT 0
Bio *string `db:"bio"` // TEXT (nullable)
IsActive bool `db:"is_active"` // BOOLEAN NOT NULL DEFAULT false
Tags []string `db:"tags"` // TEXT[]
}| Go type | SQL type |
|---|---|
| string | TEXT |
| int / int32 | INTEGER |
| int64 | BIGINT |
| float64 | FLOAT |
| bool | BOOLEAN |
| time.Time | TIMESTAMPTZ |
| uuid.UUID | UUID |
| []string | TEXT[] |
| []byte | BYTEA |
| *T (pointer) | T (nullable) |
Add to your Makefile:
migrate-diff:
gomigrate --diff
migrate-generate:
@if [ -z "$(NAME)" ]; then echo "Usage: make migrate-generate NAME=your_name"; exit 1; fi
gomigrate --generate $(NAME)Usage:
make migrate-diff
make migrate-generate NAME=add_profile_pic
make migrate-up- Does not detect column drops (safe by design — dropping is dangerous)
- Does not detect index changes
- Does not detect constraint changes
- New tables are fully generated, existing tables only get ALTER statements
PRs welcome! This fills a real gap in the Go ecosystem.