How Golang DB migration tool work?

Simplify Complexity
2 min readJan 28, 2022


Database migrations tool is written in Go. Use as CLI or import as a library.

  • Migrate reads migrations from sources and applies them in the correct order to a database.

The migration tool uses a schema_migrations table. One table exists for one DB.

mysql> select * from schema_migrations;
| version | dirty |
| 33 | 0 |
1 row in set (0.00 sec)

The command to apply all migrations to a DB would check-in schema_migrations table and pick migrations after the version (for the current case – 34 and onwards).

migration upmigration down 33

The down migration executes the down file for version 33 and updates the schema_migrations table.


Migration files are read from 1..N if no version is specified.


// read reads either up or down migrations from source `from` to `to`.// Each migration is then written to the ret channel.// If an error occurs during reading, that error is written to the ret channel, too.// Once read is done reading it will close the ret channel.
func (m *Migrate) read(from int, to int, ret chan<- interface{})


  1. no migration found for version
    Explanation: The migration version was updated in schema_registry marked dirty but the migration files are deleted/ missing. So maybe the previous migration was done with N and then Nth files were deleted. Now up or down would not work as the schema_registry has version N.
    So the solution is either to bring back Nth migrations or force the schema_regsitry version to N-1.
    migrate force N-1
  2. error: Dirty database version 32. Fix and force version.
    Explanation: The 33rd migration file was corrupted or had an error.
  • mysql> select * from schema_migrations;
    | version | dirty |
    | 32 | 1 |
    1 row in set (0.01 sec)

Manually undo the changes of version 33 (refer to 33 down migration file) and run migrate force 32


Simplify Complexity

Golang, Distributed Systems, File Systems, Python, C/C++, Linux