Can be used with any database library that implements the standard interfaces.
GoSMig 💫 in action:
Database Agnostic - Works with any database that implements a subset of Go's standard database/sql interfaces (see the Core Types section lower for more details)
Type-Safe - Full Go generics support for compile-time type safety
Flexible - Supports both transactional and non-transactional migrations
Simple - Minimal API with clear semantics
CLI-Ready - No actual CLI is provided, but a built-in command-line interface handler makes it easy to build your own CLI tool
Timeouts - Configurable operation timeouts
Robust Error Handling - Validation, version conflict detection, transaction safety, and clear error messages
Rollback Support - Safe migration rollbacks
Status Tracking - View migration status with paging support
Tested - Comprehensive test suite with PostgreSQL integration tests
Zero Dependencies - No external dependencies, only the Go standard library (and golang.org/x/term for pager support - i.e. for pagination - in the status command output)
ℹ️ NOTEs:
You will need a database driver (e.g., pgx for PostgreSQL) and optionally sqlx.
These are not dependencies of gosmig itself: while pgx and sqlx show up in go.mod, they are used only in the examples and tests - gosmig does not actually depend on them.
💡 Check the examples branch for complete, runnable examples.
Once you've built your migration tool, use it from the command line:
# Apply all pending migrations./your-migration-tool "postgres://user:pass@localhost:5432/dbname?sslmode=disable" up[x] Applied migration version 1[x] Applied migration version 2[x] Applied migration version 33 migration(s) applied
# Apply only the next migration./your-migration-tool "postgres://user:pass@localhost:5432/dbname?sslmode=disable" up-one[x] Applied migration version 41 migration(s) applied
# Roll back the last migration./your-migration-tool "postgres://user:pass@localhost:5432/dbname?sslmode=disable" down[x]-->[ ] Rolled back migration version 4
Running multiple migration processes at the same time can lead to conflicting writes.
Use a database-level advisory lock (or the closest equivalent) to ensure only one
gosmig instance runs at a time:
PostgreSQL: call SELECT pg_try_advisory_lock(...) before starting migrations and
SELECT pg_advisory_unlock(...) afterwards. Choose a consistent 64-bit key so all
processes compete for the same lock.
MySQL / MariaDB: wrap migration runs with SELECT GET_LOCK('gosmig', timeout)
and SELECT RELEASE_LOCK('gosmig') using a shared lock name.
SQL Server: use sp_getapplock / sp_releaseapplock with a well-known
resource name.
SQLite: serialize runs with a file lock (one process) or by executing
BEGIN EXCLUSIVE on a dedicated coordination table before applying migrations.
This pattern keeps migrations simple while preventing concurrent runs from stepping on each other.
For convenience, gosmig provides type aliases for common use cases:
// For database/sqltypeMigrationSQL=Migration[*sql.Row, sql.Result, *sql.Tx, *sql.TxOptions, *sql.DB]
typeUpDownSQL=UpDown[*sql.Row, sql.Result, *sql.Tx]
typeUpDownNoTXSQL=UpDown[*sql.Row, sql.Result, *sql.DB]
// Define your own for sqlxtypeMigrationSQLX=Migration[*sql.Row, sql.Result, *sql.Tx, *sql.TxOptions, *sqlx.DB]
typeUpDownNoTXSQLX=UpDown[*sql.Row, sql.Result, *sqlx.DB]
// Note: UpDownSQL works for both database/sql and sqlx
gosmig automatically creates a gosmig table to track applied migrations:
Version Conflicts: Prevents applying migrations if database version changes during execution
Transaction Safety: Automatic rollback on errors in transactional migrations
Clear Error Messages: Descriptive error messages with context
# Run tests with local PostgreSQL
make test# Run tests with Docker PostgreSQL
make test-docker
# Clean up Docker containers# NOTE: this doesn't need to be run as `make test-docker` already does it - it# is provided here "just in case".
make test-docker-down
PostgreSQL database (local or Docker)
Go 1.25+
Go 1.25+
golangci-lint for linting
govulncheck for vulnerability scanning
# Lint code
make lint
# Check for vulnerabilities
make vulncheck
# Build (includes linting and vulnerability checks)
make build
# Build only (skip checks)
make build-only
# Run tests
make test# Test with Docker
make test-docker
See Makefile for all available development commands.
gosmig works with any database that implements Go's standard database/sql interfaces. Tested with: