Writing Migrations
Structure
Each migration file is a Go file in internal/migrations/ with:
- An
init()function that registers the migration with the migrator - An
upfunction that applies schema changes - A
downfunction that reverts schema changes
Registration
func init() {
migration.GetMigrator().AddMigration(&migration.Migration{
Version: "20250706000001",
Up: mig_users_up,
Down: mig_users_down,
})
}The version should be a timestamp-based string (format: YYYYMMDDHHMMSS). The CLI auto-generates this when you run:
lemmego g migration create_users_tableWriting Up Migrations
Create Table
func mig_up(tx *sql.Tx) error {
schema := migration.Create("users", func(t *migration.Table) {
t.BigIncrements("id")
t.String("name").NotNull()
t.String("email").Unique()
t.String("password").NotNull()
t.Timestamps()
}).Build()
_, err := tx.Exec(schema)
return err
}Alter Table
func mig_up(tx *sql.Tx) error {
schema := migration.Alter("users", func(t *migration.Table) {
t.String("phone").Nullable().After("email")
t.Boolean("is_verified").Default(false)
}).Build()
_, err := tx.Exec(schema)
return err
}Drop Table
func mig_up(tx *sql.Tx) error {
_, err := tx.Exec(migration.Drop("old_sessions"))
return err
}Foreign Keys
func mig_up(tx *sql.Tx) error {
schema := migration.Create("posts", func(t *migration.Table) {
t.BigIncrements("id")
t.String("title").NotNull()
t.Text("body")
t.ForeignID("user_id").Constrained()
t.Timestamps()
}).Build()
_, err := tx.Exec(schema)
return err
}With Indexes
func mig_up(tx *sql.Tx) error {
schema := migration.Create("posts", func(t *migration.Table) {
t.BigIncrements("id")
t.String("slug").Unique()
t.String("status")
t.Index("status")
}).Build()
_, err := tx.Exec(schema)
return err
}Writing Down Migrations
The down function should revert what the up function did:
func mig_down(tx *sql.Tx) error {
_, err := tx.Exec(migration.Drop("posts"))
return err
}Or for alter operations:
func mig_down(tx *sql.Tx) error {
schema := migration.Alter("users", func(t *migration.Table) {
t.DropColumn("phone")
}).Build()
_, err := tx.Exec(schema)
return err
}Complete Example
package migrations
import (
"database/sql"
"github.com/lemmego/migration"
)
func init() {
migration.GetMigrator().AddMigration(&migration.Migration{
Version: "20250706000001",
Up: mig_users_up,
Down: mig_users_down,
})
}
func mig_users_up(tx *sql.Tx) error {
schema := migration.Create("users", func(t *migration.Table) {
t.BigIncrements("id")
t.String("name").NotNull()
t.String("email").Unique().NotNull()
t.String("password").NotNull()
t.Timestamps()
t.SoftDeletes()
}).Build()
_, err := tx.Exec(schema)
return err
}
func mig_users_down(tx *sql.Tx) error {
_, err := tx.Exec(migration.Drop("users"))
return err
}