Короткий ответ
Безопаснее разделить изменение на expand-contract и отложить физическое удаление колонки за пределы окна, либо, если удаление необходимо сейчас, заранее подготовить явный план откатa с восстановлением колонки из бэкапа — откат кода без откатa данных не восстанавливает удалённые данные.
Как это работает подробнее
откат кода не откатывает миграцию схемы автоматически; если миграция уже удалила колонку, откат на версию, которая её ожидает, приведёт к ошибкам на уровне БД, а не к восстановлению работоспособности — rollback кода и rollback схемы нужно синхронизировать явно.
Пример кода
migration.sql
-- Безопасный для окна вариант: только расширение, без удаления
ALTER TABLE users ADD COLUMN email_normalized VARCHAR(255);
-- удаление старой колонки переносится на отдельный релиз после стабильности
-- Если удаление обязательно в это окно — заранее:
-- 1) pg_dump --table=users перед миграцией
-- 2) протестированный на staging скрипт восстановления колонки из бэкапа
-- 3) чеклист: "если за 40 минут после деплоя error rate не стабилизировался — restore из бэкапа"Что использовать на практике
- Рекомендация. для жёсткого окна разумно не выполнять удаление в это же окно — только добавление нового и перенос чтения/записи; если удаление обязательно сейчас, заранее делают бэкап таблицы и готовят протестированный на staging скрипт восстановления с измеренным временем, укладывающимся в окно.
- Компромисс. expand-contract резко снижает риск потери данных, но не выполняет удаление в заявленный срок; немедленное удаление с подготовленным восстановлением выполняет задачу в срок, но требует подготовительной работы и несёт остаточный риск, если restore займёт больше времени, чем на staging. Критерий выбора — жёсткость дедлайна, объём данных и наличие протестированного процесса восстановления.
Подводные камни
- Риск. полагаться только на
git revertи повторный деплой как на «план Б» для несовместимой миграции без проверки совместимости данных; не тестировать сам процесс восстановления заранее на staging.