sql-migrate
A SQL schema migration tool for Go, usable as a standalone CLI or embedded directly as a library.
Repository Health
Technical Analysis
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-migrateCLI withup,down,redo,status,new, andskipcommands driven by a YAMLdbconfig.ymlper-environment config - A
migrate.Exec/ExecMaxlibrary API to run the same migrations programmatically from inside a Go application - Five pluggable
MigrationSourceimplementations (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
notransactionopt-out for statements that can’t run inside a transaction (e.g. concurrent index creation) - Typed
PlanError/TxErrorresults 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.FSand 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 withstatus
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.
Used by 3 apps in this directory
Authgear
Authentication
Open-source, self-hostable authentication platform with passkeys, biometric login, SSO, MFA, and GraphQL admin API — a full Auth0/Clerk/Firebase alternative for SaaS and mobile apps.
Convoy
Developer Tools · Devops
Convoy is an open-source, cloud-native webhooks gateway that ingests events over HTTP or straight from Kafka, SQS, Google Pub/Sub, and RabbitMQ, then reliably delivers them to subscriber endpoints with signed payloads, automatic retries, circuit breaking, and JavaScript-based transformations.
Fathom Lite
Analytics
A simple, self-hosted website analytics tool built with Go and Preact that lets you understand your traffic without handing data to third parties.