Миграции схем Convex без поломки продакшена: смена типов полей, добавление обязательных полей, реструктуризация таблиц. Безопасные поэтапные изменения.
Convex Migration Helper
Безопасная миграция схем и данных Convex при внесении критических изменений.
Когда использовать
- Добавление новых обязательных полей в существующие таблицы.
- Изменение типов или структуры полей.
- Разделение или слияние таблиц.
- Переименование или удаление полей.
- Миграция от вложенных к реляционным данным.
Когда НЕ использовать
- Новая схема без данных в production или dev.
- Добавление опциональных полей без необходимости backfill.
- Добавление или удаление индексов без проблем корректности.
Ключевые концепции
Валидация схемы определяет рабочий процесс
Convex не позволит задеплоить схему, не соответствующую данным в хранилище. Это фундаментальное ограничение, определяющее каждую миграцию:
- Нельзя добавить обязательное поле, если у существующих документов его нет.
- Нельзя изменить тип поля, если существующие документы имеют старый тип.
- Нельзя удалить поле из схемы, если существующие документы его содержат.
Отсюда предсказуемый паттерн: расширить схему → мигрировать данные → сузить схему.
Online-миграции
Миграции Convex выполняются онлайн: приложение продолжает обслуживать запросы, пока данные обновляются асинхронно пакетами. В процессе миграции код должен обрабатывать оба формата.
Предпочитайте новые поля изменению типов
При изменении формы данных создавайте новое поле, а не модифицируйте существующее. Это делает переход безопаснее и проще для откат.
Безопасные изменения (миграция не нужна)
// Добавление опционального поля — безопасно
users: defineTable({
name: v.string(),
bio: v.optional(v.string()), // новое опциональное поле
});
Критические изменения: рабочий процесс с несколькими деплоями
Деплой 1 — Расширение схемы:
- Обновить схему: разрешить оба формата (добавить опциональное новое поле).
- Обновить код: читать оба формата.
- Обновить код: записывать новый формат для новых документов.
- Задеплоить.
Между деплоями — Миграция данных:
- Запустить миграцию для backfill существующих документов.
- Убедиться, что все документы мигрированы.
Деплой 2 — Сужение схемы:
- Обновить схему: требовать только новый формат.
- Удалить код, обрабатывающий старый формат.
- Задеплоить.
Использование компонента миграций
Для любой нетривиальной миграции используйте компонент @convex-dev/migrations. Он обрабатывает: пакетирование, пагинацию на основе cursor, отслеживание состояния, возобновление после сбоя, dry runs и мониторинг прогресса.
# Dry run (проверка без изменений)
npx convex run migrations:myMigration '{"dryRun": true}'
# Запуск миграции
npx convex run migrations:myMigration
Типичные ошибки
- Обязательное поле до миграции данных — Convex отклонит деплой. Всегда сначала расширяйте схему.
- Использование
.collect() на больших таблицах — приводит к таймаутам. Используйте компонент миграций с батчингом.
- Нет записи нового формата до миграции — документы, созданные в окне миграции, будут пропущены.
- Пропуск dry run — используйте
dryRun: true для проверки логики до commit в production.
- Преждевременное удаление полей — предпочтительнее отметить как
v.optional с комментарием об устаревании.
- Cron'ы для батчей миграции — компонент миграций обрабатывает батчинг внутренне через рекурсивное планирование.
Чек-лист миграции
- Определено критическое изменение, спланирован рабочий процесс с несколькими деплоями.
- Схема обновлена для поддержки обоих форматов.
- Код обновлён для чтения обоих форматов.
- Код обновлён для записи нового формата для новых документов.
- Расширенная схема и обновлённый код задеплоены.
- Миграция протестирована с
dryRun: true.
- Миграция запущена, статус отслеживается.
- Все документы мигрированы.
- Схема обновлена для требования только нового формата.
- Финальная схема и код задеплоены.