Назад
Golang

golang-migrate: почему стоит остановиться именно на нем?

Если вам нужен инструмент миграций, который:

  • работает абсолютно одинаково в Go, Python, Node.js, Rust, CI/CD-скриптах
  • поддерживает почти все популярные БД (PostgreSQL, MySQL, SQLite)
  • максимально предсказуем и прозрачен
  • легко встраивается в любые пайплайны деплоя

то golang-migrate - это по-сути лучший выбор.

Почему он так хорош?

Коротко - это SQL-файлы со скриптами. Нет никакой магии, нет сюрпризов и упрощения. Но и нет подводных камней, которые часто скрывают библиотеки

Как это работает?

  1. Одна миграция - одно логическое изменение
  2. Всегда создаете файлы .up.sql и .down.sql (даже если не откатываете таблицу)
  3. Делайте миграции идемпотентными где возможно: IF NOT EXISTS, CREATE OR REPLACE
  4. Не храните данные в миграциях (кроме случаев, когда они должны быть заполнены статично)
  5. Называйте файлы последовательно и описательно
    20260130123456_users.up.sql
  6. Тестируйте up → down → up локально перед выкаткой в прод

Пример миграции (Postgres)

-- 20260130123456_create_users.up.sql
CREATE TABLE IF NOT EXISTS users (
    id            BIGSERIAL PRIMARY KEY,
    email         TEXT NOT NULL UNIQUE,
    password_hash TEXT NOT NULL,
    role          TEXT NOT NULL DEFAULT 'user',
    created_at    TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at    TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_users_email ON users USING btree (email);
-- 20260130123456_create_users.down.sql
DROP TABLE IF EXISTS users CASCADE;UPDATE users SET email = old_email;

ALTER TABLE users
    ALTER COLUMN email SET NOT NULL,
    ADD CONSTRAINT users_email_unique UNIQUE (email);(В down-миграции — обратный процесс)

Как интегрировать в проект

Можно через Makefile / CI

migrate:
    migrate -path ./migrations -database "${DATABASE_URL}"  up

Это будет самы лучший вариант, в ci/cd можно добавить вызов этой этого скрипта перед сборкой приложения

В каких случаях точно стоит использовать

  • Микросервисы на разных языках
  • Строгий GitOps / CI/CD (ArgoCD, GitHub Actions, etc.)
  • Нужно поддерживать много разных БД в компании
  • Важна максимальная предсказуемость и минимум магии

Личный опыт

На мой взгляд это самый лучший вариант миграций, он более "долгий" в процессе разработки новых реп, но в конечном итоге - более предсказуемый, а также более ультимативный. Вы можете добавить туда любой sql без костылей, что упростит вам развитие сервиса в дальнейшем, и я почти уверен, что вам никогда не придется его переписывать на библиотеку и всякие "авто-миграторы" из структур. Что может быть лучше?)

Ну и еще одно преимущество, которое можно упустить.- низкий порог входа. Любой бекенд-разработчик знает sql, и легко напишет такую миграцию. А вот со всякими либами нужно порой разбираться отдельно…