GoMigrate is a SQL migration library for Go. It can support multiple databases such as SQLite, PostgreSQL, MySQL, and others.
Click to expand
- Go 1.24 or later
- SQLite, PostgreSQL, MySQL, or other databases
- Go driver for the database you want to use
go get github.com/topi314/gomigrate
Create a new folder named migrations
and create a file with the following naming convention VERSION_NAME.sql
(VERSION_NAME.DRIVER.sql
) where VERSION
is a number, NAME
is a name of the migration & DRIVER
(optional) is the name of the database driver this migration is for.
As an example: 01_create_users_table.sql
, 01_create_users_table.postgres.sql
, 02_add_email_to_users_table.sql
or 02_add_email_to_users_table.sqlite.sql
.
01_create_users_table.sql
-- create users table
CREATE TABLE users
(
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL
);
01_create_users_table.postgres.sql
-- create users table for PostgreSQL
CREATE TABLE users
(
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL
);
02_add_email_to_users_table.sql
-- add email column to users table
ALTER TABLE users
ADD COLUMN email VARCHAR;
02_add_email_to_users_table.sqlite.sql
-- add email column to users table for SQLite
ALTER TABLE users
ADD COLUMN email VARCHAR;
It should look like this:
migrations/
├─ 01_create_users_table.sql
├─ 01_create_users_table.postgres.sql
├─ 02_add_email_to_users_table.sql
├─ 02_add_email_to_users_table.sqlite.sql
Alternatively you can also organize your migrations into dirver subdirectories:
migrations/
├─ postgres/
│ ├─ 01_create_users_table.sql
│ ├─ 02_add_email_to_users_table.sql
├─ sqlite/
│ ├─ 01_create_users_table.sql
│ ├─ 02_add_email_to_users_table.sql
In this case no DRIVER
suffix is allowed in the migration file name.
Now you can run the migrations in your Go code. Here is an example for SQLite:
package main
import (
"context"
"database/sql"
"embed"
"log"
"log/slog"
"time"
_ "modernc.org/sqlite"
"github.com/topi314/gomigrate"
"github.com/topi314/gomigrate/drivers/sqlite"
)
//go:embed migrations/*.sql
var migrations embed.FS
func main() {
// open database
db, err := sql.Open("sqlite", "database.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// create context with timeout
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// run migrations
if err = gomigrate.Migrate(ctx, db, sqlite.New, migrations,
gomigrate.WithDirectory("migrations"), // set directory for migrations
gomigrate.WithTableName("gomigrate"), // set custom table name for migrations
gomigrate.WithLogger(slog.Default()), // set custom logger
); err != nil {
log.Fatal(err)
}
// run your code
}
You can find examples under
For help feel free to open an issue.
Contributions are welcomed but for bigger changes please first create an issue to discuss your intentions and ideas.