go-migrationGo Migration
Migrations
Documentation

Migration Status

Check which migrations have run and their batch numbers using m.Status().

Migration Status

Use m.Status() to inspect the current state of all registered migrations — which ones have run, their batch numbers, and which are still pending.

Using m.Status()

go
statuses, err := m.Status()
if err != nil {
    log.Fatal(err)
}

for _, s := range statuses {
    fmt.Printf("Migration: %s | Applied: %v | Batch: %d\n", s.Name, s.Applied, s.Batch)
}

m.Status() returns a []migrator.MigrationStatus, one entry for each registered migration.

Read-Only Behavior

m.Status() never writes to the database:

  • It does not create the tracking table. If the table does not exist yet, every registered migration is reported as pending.
  • It does not take the migration lock, so it never waits for a running migration.

This makes it safe to call from health checks, readiness probes, or a separate monitoring process.

Before v1.2.0, m.Status() created the tracking table if it was missing. It is now strictly read-only.

Status Output

Each status entry contains:

FieldTypeDescription
NamestringThe migration name as passed to m.Register()
AppliedboolWhether the migration has been applied
BatchintThe batch number (0 if not yet applied)
AppliedAt*time.TimeWhen the migration was applied (nil if not yet applied)

Example Output

Given these registered migrations:

go
m.Register("20240101000001_create_users_table", &migrations.CreateUsersTable{})
m.Register("20240115000001_create_posts_table", &migrations.CreatePostsTable{})
m.Register("20240201000001_add_phone_to_users", &migrations.AddPhoneToUsers{})

If the first two have been applied, m.Status() produces:

Migration: 20240101000001_create_users_table   | Applied: true  | Batch: 1
Migration: 20240115000001_create_posts_table   | Applied: true  | Batch: 1
Migration: 20240201000001_add_phone_to_users   | Applied: false | Batch: 0

Complete Example

main.go
package main

import (
    "database/sql"
    "fmt"
    "log"

    _ "github.com/lib/pq"

    "github.com/gopackx/go-migration/pkg/migrator"

    "github.com/gopackx/go-migration/pkg/schema/grammars"
    "your-project/migrations"
)

func main() {
    db, err := sql.Open("postgres", "postgres://user:password@localhost:5432/mydb?sslmode=disable")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    m := migrator.New(db, migrator.WithGrammar(grammars.NewPostgresGrammar()))

    if err := m.Register("20240101000001_create_users_table", &migrations.CreateUsersTable{}); err != nil {
        log.Fatal(err)
    }
    if err := m.Register("20240115000001_create_posts_table", &migrations.CreatePostsTable{}); err != nil {
        log.Fatal(err)
    }
    if err := m.Register("20240201000001_add_phone_to_users", &migrations.AddPhoneToUsers{}); err != nil {
        log.Fatal(err)
    }

    statuses, err := m.Status()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println("Migration Status:")
    fmt.Println("─────────────────────────────────────────────────────")
    for _, s := range statuses {
        status := "Pending"
        if s.Applied {
            status = fmt.Sprintf("Applied (Batch %d)", s.Batch)
        }
        fmt.Printf("  %s — %s\n", s.Name, status)
    }
}

m.Status() only reports on migrations that are registered with the migrator. If a migration was previously run but is no longer registered, it won't appear in the status output.

Checking for Pending Migrations from the CLI

The migrate:status command prints the same information as a table. Add --check to exit with status 1 (after printing the table, and with N migration(s) pending on stderr) when anything is pending — useful as a CI step or as a readiness gate that waits for a migration Job to finish:

bash
go-migration migrate:status --check

# Block until every migration has been applied
until go-migration migrate:status --check; do sleep 5; done

In your own code, the equivalent is to count the entries with Applied == false:

go
pending := 0
for _, s := range statuses {
    if !s.Applied {
        pending++
    }
}
if pending > 0 {
    log.Fatalf("%d migration(s) pending", pending)
}

See Concurrency and Locking for a Kubernetes example.

What's Next?