Golang Migrate is a powerful and widely used database migration tool for Go applications. It provides a simple CLI and Go library to handle schema changes in a consistent and version-controlled way. As of April 2025, Golang Migrate (v4.18.2) is still a top choice in the Go community for managing database structure updates across development, staging, and production environments.
How to Install Golang Migrate?
You can install golang-migrate using pre-built binaries or platform-specific package managers, depending on your operating system and preferences.
Option 1: Pre-built Binaries
For any platform (Windows, MacOS, Linux):
curl -L <https://github.com/golang-migrate/migrate/releases/download/$version/migrate.$os-$arch.tar.gz> | tar xvz
Option 2: Platform Package Managers
- For MacOS:
brew install golang-migrate
- For Windows (using Scoop):
scoop install migrate
- For Linux (Debian/Ubuntu):
curl -L <https://packagecloud.io/golang-migrate/migrate/gpgkey> | apt-key add -
echo "deb <https://packagecloud.io/golang-migrate/migrate/ubuntu/> $(lsb_release -sc) main" > /etc/apt/sources.list.d/migrate.list
apt-get update
apt-get install -y migrate
These commands will install the latest stable version, which as of April 2025 is v4.18.2
.
Basic CLI Usage
Create Migration Files
To create a new migration:
migrate create -ext sql -dir database/migration/ -seq create_users_table
This command generates two files:
000001_create_users_table.up.sql
- For applying the migration000001_create_users_table.down.sql
- For reverting the migration
Run Migrations
To apply all pending migrations:
migrate -source file://path/to/migrations -database postgres://localhost:5432/database up
To apply a specific number of migrations:
migrate -source file://path/to/migrations -database postgres://localhost:5432/database up 2
To roll back migrations
migrate -source file://path/to/migrations -database postgres://localhost:5432/database down
To roll back a specific number of migrations:
migrate -source file://path/to/migrations -database postgres://localhost:5432/database down 2
For GitHub-hosted migrations:
migrate -source github://username:token@repository/path -database postgres://localhost:5432/database up
Using Golang Migrate in Go Projects
Golang Migrate can be imported directly into your Go application, allowing programmatic control over migrations.
Import and Use Migrate
import (
"github.com/golang-migrate/migrate/v4"
_ "github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/file"
)
func main() {
m, err := migrate.New(
"file:///path/to/migrations",
"postgres://localhost:5432/database?sslmode=enable")
if err != nil {
// Handle error
}
// Apply all migrations
if err := m.Up(); err != nil {
// Handle error
}
// Or apply a specific number of migrations
if err := m.Steps(2); err != nil {
// Handle error
}
}
Use Existing Database Connection
import (
"database/sql"
_ "github.com/lib/pq"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/file"
)
func main() {
db, err := sql.Open("postgres", "postgres://localhost:5432/database?sslmode=enable")
if err != nil {
// Handle error
}
driver, err := postgres.WithInstance(db, &postgres.Config{})
if err != nil {
// Handle error
}
m, err := migrate.NewWithDatabaseInstance(
"file:///migrations",
"postgres",
driver)
if err != nil {
// Handle error
}
// Run migrations
if err := m.Up(); err != nil {
// Handle error
}
}
Best Practices for Effective Migrations
Use Consistent Naming
Follow consistent naming patterns for migration files:
- Use sequential numbering (
001
,002
, etc.) - Include descriptive names (
create_users_table
,add_email_field
) - Use lowercase and underscores for clarity
One Change per Migration
Each migration should perform a single logical change:
- Smaller migrations are easier to review and debug
- Focused changes reduce the risk of conflicts
- Simple migrations are easier to roll back if needed
Make Migrations Idempotent When Possible
Idempotent migrations can be safely applied multiple times without changing the result:
-- Example of idempotent migration
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
username VARCHAR(100) NOT NULL
);
-- Add column if it doesn't exist
DO $$
BEGIN
IF NOT EXISTS (
SELECT FROM information_schema.columns
WHERE table_name='users' AND column_name='email'
) THEN
ALTER TABLE users ADD COLUMN email VARCHAR(255);
END IF;
END
$$;
Use Transactions for Safety
Wrap migrations in transactions to ensure atomicity:
BEGIN;
-- Migration steps here
COMMIT;
This prevents partial migrations that could leave your database in an inconsistent state.
Never Edit Existing Migrations
Once a migration has been applied to any environment:
- Consider it immutable
- Create new migrations for additional changes
- This prevents inconsistencies between environments
- Maintains a clear history of database evolution
Version Control Your Migrations
Store migrations in version control alongside application code:
- Ensures changes are tracked
- Enables code review of database changes
- Preserves the history of schema evolution
Recent Updates
As of April 2025, the most recent stable release is v4.18.2, which includes several improvements:
- Bug fixes for MySQL when using
sql_safe_update
- Improved error messages for invalid sources and databases
- Updated support for latest PostgreSQL 16, MySQL 8.4 and 9.0
- Support for newer Ubuntu releases (including Noble Numbat 24.04)
- Various security updates and dependency upgrades
Integrating with Atlas for Schema Planning
For developers seeking more advanced migration planning, Atlas integration offers automatic migration planning capabilities:
- Atlas can calculate differences between current and desired database states
- It generates migration plans based on those differences
- This allows for declarative database schema management
- Integrates seamlessly with existing golang-migrate workflows
To set up Atlas with golang-migrate, create a project configuration file named atlas.hcl
:
env "local" {
src = "file://schema.sql"
dev = "docker://mysql/8/dev"
migration {
dir = "file://migrations"
format = golang-migrate
}
}
>> Read more:
- How to Work with PostgreSQL in Golang using pgx Package?
- A Comprehensive Guide To Dockerize A Golang Application
Conclusion
Golang Migrate offers a powerful, flexible approach to database schema management, bridging the gap between application development and database evolution. Its clean design, extensive feature set, and strong community support make it an excellent choice for Go developers looking to implement robust, version-controlled database migrations.
Whether used through the CLI for straightforward operations or integrated into code for programmatic control, golang-migrate provides the tools necessary for maintaining consistent, reliable database states across all environments of your application lifecycle.
>>> Follow and Contact Relia Software for more information!
- golang
- coding
- Web application Development