Неприятная пятница. Выкатили релиз, в нём миграция, которая удаляла колонку orders.legacy_status и переносила всё на новый статус. Через 15 минут посыпались ошибки в оплате, откатили код на прошлый релиз, а старый код хочет legacy_status, которой уже нет. Вернули колонку руками, значения восстановили из ночного бэкапа и логов, к девяти вечера всё работало. Хочу договориться в команде, чтобы такое не повторялось. Как у вас: миграции отдельно от кода, правило «никогда не удалять в том же релизе», что-то ещё? Rails 7.1, Capistrano, шесть человек.
Правило, которое я видел работающим: любая миграция в релизе совместима с кодом прошлого релиза. Тогда откат кода всегда безопасен, а схему назад не откатывают вообще, только вперёд. Удаление колонки всегда отдельным релизом, минимум через неделю после того, как её перестали читать.
Я бы записал в договорённости по шагам, по схеме расширения и сжатия:
1. релиз N: добавляем новое, старое не трогаем, код пишет в оба места;
2. перенос данных отдельной задачей, не в деплое;
3. релиз N+1: код читает только новое;
4. релиз N+2, через неделю: удаляем старое.
Откат в любой точке безопасен, потому что прошлый релиз понимает текущую схему. А проверять это можно в CI: прогонять тесты прошлого релиза на схеме после новых миграций. Дольше на неделю, зато пятница остаётся пятницей.
Я бы делала ещё бэкап конкретной таблицы прямо перед деструктивной миграцией, а не только ночной. Полдня сэкономит.
Про Capistrano: cap production deploy:rollback откатывает только код, миграции он не трогает. Многие узнают об этом ровно в такую пятницу