> Кто пишет миграции в проекте (Go)

Уровень: middle · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: Wildberries

Стек: Go

> Пример ответа

Короткий ответ

В Go-проектах миграции обычно пишет backend-разработчик, который владеет контекстом изменений схемы данных. Это может быть автор фичи, требующей изменения БД, или выделенный инженер, отвечающий за работу с базой данных. В крупных командах процесс часто регламентирован: миграции проходят код-ревью и применяются через CI/CD. Главное - чтобы автор миграции понимал целевую схему, умел обращаться с инструментами (golang-migrate, goose, atlas) и учитывал обратную совместимость.

Подробное объяснение

Вопрос о том, кто пишет миграции, на самом деле про распределение ответственности и процесс. В Go-экосистеме нет единого стандарта, поэтому практики различаются.

Вариант 1: автор фичи. Самый распространённый подход. Разработчик, который меняет код, связанный с данными, сам пишет миграцию. Это логично, потому что он лучше всех знает, какие поля нужны, какие индексы требуются и как данные будут использоваться. Такой подход ускоряет разработку, но требует дисциплины: миграция должна быть проверена на реальных данных, а не только на локальной БД.

Вариант 2: выделенный DBA или инженер по данным. В компаниях с большими объёмами данных или строгими требованиями к доступности миграции пишет отдельный человек. Он отвечает за производительность, блокировки, время выполнения и безопасность. Разработчик в этом случае только описывает требования, а DBA превращает их в SQL.

Вариант 3: смешанный подход. Разработчик пишет черновик миграции, а DBA или tech lead ревьюит его и дорабатывает. Так делают, когда команда хочет сохранить скорость, но не хочет рисковать продакшеном.

Инструменты в Go. Чаще всего используют golang-migrate или goose. Оба поддерживают версионирование, up/down миграции и интеграцию с Go-кодом. Atlas позволяет описывать схему декларативно и генерировать миграции автоматически. Выбор инструмента влияет на то, как миграции выглядят и как их применяют.

Процесс. Миграции должны быть частью код-ревью. Важно проверять не только SQL, но и порядок применения, отсутствие деструктивных операций без необходимости, наличие down-миграций. В CI/CD миграции обычно применяются автоматически перед деплоем, но для больших таблиц может потребоваться ручной запуск в окно обслуживания.

На практике

В реальных проектах я рекомендую следующий подход:

  1. Миграцию пишет разработчик, который вносит изменения в код, связанный с БД. Это его зона ответственности.
  2. Обязательно код-ревью с участием хотя бы одного человека, который хорошо знает схему данных и умеет замечать проблемы с производительностью.
  3. Если в команде есть DBA - он подключается на этапе ревью или перед деплоем на прод.
  4. Миграции применяются через CI/CD, но с возможностью отката. Для критичных изменений (ALTER TABLE на большой таблице) - отдельный процесс с согласованием времени.

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

Пример кода

Пример миграции с использованием golang-migrate:

SQL
-- 000001_create_users.up.sql
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_users_created_at ON users (created_at);
SQL
-- 000001_create_users.down.sql
DROP TABLE IF EXISTS users;

Пример миграции с goose:

GO
package migrations
import (
"database/sql"
"github.com/pressly/goose/v3"
)
func init() {
goose.AddMigration(Up, Down)
}
func Up(tx *sql.Tx) error {
_, err := tx.Exec(`
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id),
total NUMERIC(10, 2) NOT NULL,
status TEXT NOT NULL DEFAULT 'new'
);
`)
return err
}
func Down(tx *sql.Tx) error {
_, err := tx.Exec(`DROP TABLE orders;`)
return err
}

Как отвечать на собеседовании

Начните с прямого ответа: миграции пишет разработчик, который владеет контекстом изменений. Затем уточните, что процесс зависит от команды и масштаба проекта. Покажите, что понимаете trade-off: скорость разработки против риска для продакшена. Упомяните инструменты, которые используете, и как выстраиваете процесс ревью и деплоя. Хорошо, если приведёте пример из практики: как вы писали миграцию, с какими проблемами столкнулись и как решали. Это покажет ваш уровень.

Что проверяет интервьюер

Интервьюер оценивает:

  • Понимание зон ответственности в команде.
  • Умение рассуждать о процессах, а не только о коде.
  • Знание инструментов для миграций в Go-экосистеме.
  • Понимание рисков, связанных с изменением схемы БД.
  • Способность аргументировать свой выбор подхода.

Важно показать, что вы не просто знаете, как написать SQL, но и понимаете, как миграции встраиваются в жизненный цикл разработки.

Типичные ошибки

  • Ответ "миграции пишет DBA" без пояснения, почему и как это работает в команде без DBA.
  • Утверждение, что миграции применяются автоматически при старте приложения - это антипаттерн для продакшена.
  • Игнорирование down-миграций или их отсутствие.
  • Непонимание разницы между инструментами (golang-migrate vs goose vs atlas).
  • Ответ без упоминания код-ревью и процесса деплоя - это показывает узкий взгляд на разработку.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью