Câu trả lời thực tế: không có thứ tự nào an toàn nếu migration không tương thích ngược, vì trong lúc rollout luôn có khoảnh khắc code cũ và code mới cùng chạy trên cùng một schema.
Vì vậy quy tắc là mọi migration phải tương thích ngược với version code đang chạy, rồi migration chạy trước khi deploy code mới (schema mở rộng trước, code dùng sau).
Mẫu expand / contract cho thao tác nguy hiểm — đổi tên cột name thành full_name:
1. Expand: thêm cột full_name, nullable. Deploy code ghi cả hai cột, đọc name.
2. Backfill: copy dữ liệu theo lô, không khóa bảng lâu.
3. Migrate đọc: deploy code đọc full_name, vẫn ghi cả hai.
4. Contract: khi chắc chắn không còn version nào đọc name (thường sau vài ngày), mới DROP COLUMN.
Mỗi bước là một lần release riêng, mỗi bước rollback được độc lập.
Chi tiết vận hành hay bị hỏi thêm:
- Thao tác khóa bảng lâu (thêm index trên bảng lớn) phải chạy không khóa (
CREATE INDEX CONCURRENTLYở Postgres) và ngoài giờ cao điểm. - Migration phải idempotent và chạy đúng một lần (advisory lock hoặc job riêng), tránh nhiều pod cùng chạy khi rollout.
DROP COLUMN/DROP TABLEkhông có đường lùi — tách hẳn khỏi release chức năng.