Skip to main content

Performing Atlas Migrations When Using Golang Migrate

Developers who use Atlas to run migrations using a golang-migrate directory format, may run into an errors like:

-- migrating version 20250324061649.down.sql
-> DROP TABLE `users`;
Error 1051 (42S02): Unknown table 'public.users'

golang-migrate is a popular migration tool used in the Go community, and Atlas supports working with its migration directory format, amongst others, through basic configurations.

golang-migrate Migration Directory

When creating schema migrations with golang-migrate, users create two empty files for each set of changes like so:

db/migrations
├── 20250324061649.down.sql
└── 20250324061649.up.sql

The files contain the intended schema changes (up) and the instructions to roll back these changes (down).

When applying migrations, you use the up command so golang-migrate knows to use the corresponding up files. When rolling back on migrations, you use the down command to golang-migrate knows to use the corresponding down files.

Applying Migrations with Atlas

The standard migrations directory for Atlas does not contain separate up and down files. Instead, it only contains files with schema migrations and applies them all in order when running migrate apply and has a separate system for rollbacks.

If a user tries executing migrate apply using a golang-migrate migrations directory setup without any flags, Atlas will assume it is a standard Atlas directory and run all the files, including the down files. Since Atlas runs the migration files in lexicographic order, the down files are typically run first, meaning that Atlas tries to run commands that revert changes that have yet to be made, leading to errors.

The Solution

To ensure that only the up migration files are run, add the format flag to the env block in atlas.hcl either as a parameter:

env "dev" {
...
migration {
dir = "file://db/migrations"
format = "golang-migrate"
}
}

or as a flag in the directory link:

env "dev" {
...
migration {
dir = "file://db/migrations?format=golang-migrate"
}
}

Alternatively, you can include the directory link with the ?format=golang-migrate flag in the command:

atlas migrate apply --dir "file://db/migrations?format=golang-migrate" --env dev

Defining a format value ensures that Atlas is aware that both up and down files exist in the migrations directory and it should only use the up files. These up files can have destructive commands in them, but they are not dropping objects that don't yet exist in the schema.