Introduction
golang-migrate is a database migration tool written in Go that works both as a standalone CLI and as an importable library. It keeps your database schema versioned and reproducible across environments. Migrations are plain SQL files or Go functions, making them easy to review and version-control.
What golang-migrate Does
- Runs forward and backward SQL migrations with sequential or timestamp-based versioning
- Supports 20+ database drivers including PostgreSQL, MySQL, SQLite, CockroachDB, and MongoDB
- Reads migration sources from local filesystem, AWS S3, Google Cloud Storage, GitHub, or Go embed
- Provides a Go library for programmatic migration control inside application startup
- Detects dirty migration state and provides tools to force-fix version conflicts
Architecture Overview
The tool is built around two abstractions: a Source interface for reading migration files and a Database interface for executing them. Each migration has an up and down file. The current version is tracked in a metadata table within the target database. When you run migrate up, it compares the current version with available files and applies pending migrations sequentially in a transaction where supported.
Self-Hosting & Configuration
- Install via Homebrew, Docker, or download prebuilt binaries from GitHub releases
- Migrations are plain .sql files named with a version prefix (e.g., 000001_create_users.up.sql)
- Database connection is specified via a URL string with driver-specific parameters
- Use environment variables or flags to configure path, database URL, and verbosity
- Embed migrations in Go binaries using the go-bindata or iofs source driver
Key Features
- Atomic migrations with transaction support on databases that allow transactional DDL
- Graceful handling of migration conflicts with force version and dirty state repair
- Docker image available for CI/CD pipeline integration without local installation
- Extensible driver system for adding support for new databases or migration sources
- Lightweight with zero external dependencies beyond the chosen database driver
Comparison with Similar Tools
- Flyway — Java-based with a richer feature set and commercial edition; heavier runtime
- dbmate — Simpler Go-based tool; fewer source drivers but easier default configuration
- Atlas — Declarative schema-as-code approach; more opinionated but handles drift detection
- Liquibase — XML/YAML-based migrations with enterprise features; steeper learning curve
- goose — Go migration tool with Go function support; smaller community but similar scope
FAQ
Q: Can I use golang-migrate without Go? A: Yes. The CLI binary is standalone and works with plain SQL files. No Go knowledge required.
Q: What happens if a migration fails halfway? A: The migration is marked as dirty. You can fix the issue and use migrate force to set the correct version before retrying.
Q: Does it support multiple database schemas? A: You can run separate migration directories per schema. The version table can be customized to avoid conflicts.
Q: How do I use it in CI/CD? A: Use the official Docker image or install the binary in your pipeline. Run migrate up with the production database URL as part of deployment.