sql-migrate

A SQL schema migration tool for Go, usable as a standalone CLI or embedded directly as a library.

Tool
Go
vv1.8.1
3,419stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
50/100Fair
Development Activity32
Maintenance4
Community64
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
66/100Good
Architecture78
Code Quality75
Innovation55
Learning Curve55

sql-migrate is a schema migration tool for Go applications that use SQL databases. It ships both as a sql-migrate command-line binary driven by a dbconfig.yml environment file and as an importable github.com/rubenv/sql-migrate package, so teams can run migrations from a deploy script or trigger them programmatically from inside their own application at startup.

Migrations are written as plain SQL files with -- +migrate Up and -- +migrate Down comment markers, and are applied atomically inside a transaction by default (with an opt-out for statements like CREATE INDEX CONCURRENTLY that can’t run inside one). Under the hood it builds on gorp for dialect handling, giving it out-of-the-box support for SQLite, PostgreSQL, MySQL, MSSQL, and Oracle from a single binary or import.

The library’s MigrationSource interface is pluggable: migrations can be read from a directory on disk, hardcoded in memory, or embedded into a single-binary deployment via Go’s embed.FS, an http.FileSystem implementation, or (for older codebases) packr/bindata. This makes it a common fit for Go services that want self-contained migration files baked into the compiled binary rather than shipped as loose SQL alongside it.

What You Get

  • A sql-migrate CLI with up, down, redo, status, new, and skip commands driven by a YAML dbconfig.yml per-environment config
  • A migrate.Exec/ExecMax library API to run the same migrations programmatically from inside a Go application
  • Five pluggable MigrationSource implementations (memory, file, embed.FS, http.FileSystem, packr/bindata) so migrations can be embedded into a single self-contained binary
  • Atomic, transactional Up/Down migrations with a notransaction opt-out for statements that can’t run inside a transaction (e.g. concurrent index creation)
  • Typed PlanError/TxError results that identify exactly which migration failed and why

Common Use Cases

  • Running schema migrations as a step in a CI/CD deploy pipeline via the CLI against a Postgres/MySQL/SQLite/MSSQL/Oracle database
  • Self-contained Go binaries that embed their own migration files with embed.FS and apply them automatically on startup
  • Multi-environment projects that need separate dev/staging/production migration configs from one dbconfig.yml
  • Rolling back a bad migration in development with redo, or auditing what has and hasn’t been applied with status

Under The Hood

Architecture The core of the project is migrate.go, which defines the Migration type, the MigrationSet configuration (table name, schema, transaction/unknown-migration flags), and a family of MigrationSource implementations — MemoryMigrationSource, FileMigrationSource, EmbedFileSystemMigrationSource, HttpFileSystemMigrationSource, and the legacy packr/bindata sources — all satisfying one interface so the execution path (Exec/ExecMax) never needs to know where migrations came from. Parsing of the -- +migrate Up/Down SQL comment syntax is factored into its own sqlparse subpackage with an independent test suite, keeping statement-splitting logic decoupled from execution and transaction handling. The sql-migrate/ CLI directory is a thin second layer built on mitchellh/cli, where each command (command_up.go, command_down.go, command_status.go, etc.) loads a dbconfig.yml via config.go and calls into the exact same core Exec API used by library consumers — a clean library/CLI split with no circular dependencies between the two.

Tech Stack Built for Go 1.25, using go-gorp/gorp/v3 for its dialect abstraction layer, with driver support wired in for go-sql-driver/mysql, lib/pq (Postgres), denisenkom/go-mssqldb, mattn/go-sqlite3, and both godror and mattn/go-oci8 for Oracle. The CLI depends on mitchellh/cli for command dispatch, olekukonko/tablewriter for the status table output, and gopkg.in/yaml.v2 for parsing dbconfig.yml. The project ships a Dockerfile, a Makefile for local dev tasks, and GitHub Actions workflows for testing and releases.

Code Quality The project carries an extensive test suite — an 800+ line migrate_test.go built on the gopkg.in/check.v1 (gocheck) framework exercising most MigrationSet code paths against an in-memory SQLite database, plus dedicated files for sorting, initialization, and pending-migration logic, and a comprehensive standalone test file for the sqlparse subpackage. Error handling is explicit and typed rather than swallowed: failures surface as PlanError or TxError values that carry the specific migration and underlying error. The repo enforces a strict golangci-lint v2 configuration (revive, staticcheck, errcheck, gocritic, unparam) plus gofumpt/goimports formatting, and GitHub Actions runs the suite on every push.

What Makes It Unique Relative to other Go schema-migration tools, sql-migrate’s distinguishing choice is its pluggable MigrationSource interface — the same execution engine can pull migrations from disk, from memory, or from assets embedded directly into a compiled binary via embed.FS (with legacy packr/bindata support retained for older codebases), without changing how migrations are written or applied. Combined with dialect coverage across five SQL databases from a single dependency and a per-statement notransaction escape hatch for engines that reject certain DDL inside a transaction, it favors flexibility of deployment shape over introducing new migration syntax or concepts.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search