convex-migrate-rehearse
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese<!-- GENERATED from convex-agents content/capabilities/migrate-rehearse.json — do not edit by hand. -->
<!-- 由 convex-agents content/capabilities/migrate-rehearse.json 生成 — 请勿手动编辑。 -->
Rehearse a schema change on a preview before prod
在生产环境前于预览环境演练Schema变更
A schema push on Convex validates every existing document against the new schema and FAILS the push if any row doesn't conform — a real data-conformance gate. The safe way to use that gate is to let it fail on a rehearsal copy, not on prod. This capability turns a preview deployment into that copy: seed it with a prod snapshot, push the new schema + run the backfill there, watch the gate, and only promote once it's green. It composes deploy-guard (target classification), migrate (the optional-then-tighten pattern), and @convex-dev/migrations (the batched, resumable backfill).
在Convex上推送schema时,会验证所有现有文档是否符合新schema,如果有任何行不符合,推送会失败——这是一个真正的数据一致性校验关卡。安全使用该关卡的方式是让它在演练副本上失败,而非生产环境。此能力将预览部署环境转化为该副本:用生产环境快照初始化它,在那里推送新schema并运行backfill,监控校验关卡,只有在验证通过后才推广到生产环境。它整合了deploy-guard(目标分类)、migrate(先可选后收紧模式)以及@convex-dev/migrations(批量、可恢复的backfill)。
Workflow
工作流程
- PRECONDITION: preview deployments need a Preview Deploy Key (dashboard → Project Settings → Deploy Keys → Preview) exported as before any
CONVEX_DEPLOY_KEY/--preview-createdeploy — a plain--preview-namesession cannot create previews, and this is a paid-tier feature. If no preview key is available, fall back to rehearsing on the personal dev deployment seeded with the snapshot, and say so.npx convex login - GUARD: deploy-guard — classify + announce the SOURCE (prod, being read) and the eventual TARGET (prod, being changed); get the fresh explicit yes for the prod promote up front and confirm the plan.
- SNAPSHOT the source data read-only: (from the deployment holding the real data; add
npx convex export --path snapshot.ziponly if the migration touches files). This is a read; it changes nothing.--include-file-storage - CREATE the preview FROM THE PRE-CHANGE CODE — do this BEFORE editing schema.ts, so the preview starts on the schema the snapshot data already conforms to: (needs the preview key; auto-expires ~5 days). Seed it:
npx convex deploy --preview-create migrate-<slug>(import targets a deployment by NAME withnpx convex import snapshot.zip --deployment migrate-<slug>; there is no--deploymentflag on import). The import succeeds because the data still matches the old schema.--preview-name - REHEARSE on the preview, in the migrate order — each push is (re-deploys to the SAME preview, keeping its data; NOT
npx convex deploy --preview-name migrate-<slug>, which targets personal dev): (a) make the new/changed field OPTIONAL and deploy — if existing rows violate it the push FAILS HERE on the copy with the offending shape; fix and re-push until green. (b) write a @convex-dev/migrations backfill and run it against the preview; verify every row is now valid. (c) tighten the validator (required / narrowed union) and deploy again — the gate now passes because the backfill ran.convex dev - VERIFY on the preview: run the app's functions against the migrated data (MCP /
runpointed at the preview, or a smoke query) to confirm behavior and shape.runOneoffQuery - PROMOTE only on the fresh explicit yes from step 1: apply the SAME sequence to prod (optional schema → backfill → tighten). Because it already succeeded on prod-shaped data, the prod push repeats a proven run. Keep the snapshot as the rollback artifact (); state plainly that data written after the snapshot is lost, so keep the promote window short.
npx convex import snapshot.zip --replace --prod - CLEAN UP: the preview auto-expires; delete the local snapshot when done (it holds real data — treat it as sensitive, never commit it).
- 前提条件:在执行任何/
--preview-create部署前,预览部署环境需要一个预览部署密钥(控制台 → 项目设置 → 部署密钥 → 预览),并导出为--preview-name——普通的CONVEX_DEPLOY_KEY会话无法创建预览环境,且这是付费层级功能。如果没有可用的预览密钥,则退回到在由快照初始化的个人开发部署环境中进行演练,并告知相关情况。npx convex login - 校验:deploy-guard —— 分类并告知源环境(正在读取的生产环境)和最终目标环境(即将变更的生产环境);提前获取生产环境推广的明确许可,并确认计划。
- 只读快照源数据:(从存储真实数据的部署环境执行;仅当迁移涉及文件时添加
npx convex export --path snapshot.zip)。这是只读操作,不会改变任何内容。--include-file-storage - 基于变更前的代码创建预览环境——在编辑schema.ts之前完成此操作,这样预览环境启动时使用的schema与快照数据已有的schema一致:(需要预览密钥;约5天后自动过期)。初始化预览环境:
npx convex deploy --preview-create migrate-<slug>(导入通过npx convex import snapshot.zip --deployment migrate-<slug>指定目标部署环境;import没有--deployment参数)。由于数据仍与旧schema匹配,导入会成功。--preview-name - 在预览环境中按migrate顺序进行演练——每次推送使用(重新部署到同一个预览环境,保留其数据;而非
npx convex deploy --preview-name migrate-<slug>,后者针对个人开发环境):(a) 将新增/修改的字段设为OPTIONAL并推送——如果现有行违反该设置,推送会在此副本上失败,显示有问题的数据结构;修复后重新推送直到验证通过。(b) 编写一个@convex-dev/migrations backfill并在预览环境中运行;验证每一行现在都有效。(c) 收紧校验规则(设为必填/缩小联合类型范围)并再次推送——由于已运行backfill,校验关卡现在会通过。convex dev - 在预览环境中验证:针对迁移后的数据运行应用的函数(指向预览环境的MCP /
run,或冒烟查询),确认行为和数据结构。runOneoffQuery - 仅在步骤1获得的明确许可下进行推广:将相同的步骤应用到生产环境(可选schema → backfill → 收紧规则)。由于该流程已在与生产环境一致的数据上成功执行,生产环境的推送是重复已验证的流程。保留快照作为回滚工件();明确说明快照恢复会丢失快照之后写入的数据,因此要缩短推广窗口。
npx convex import snapshot.zip --replace --prod - 清理:预览环境会自动过期;完成后删除本地快照(它包含真实数据——视为敏感数据,绝不要提交到版本库)。
Rules
规则
- Create the preview from the PRE-CHANGE code and seed the snapshot BEFORE editing schema.ts — so the import conforms and the conformance gate then fails on the copy (not prod) when you push the change; each preview push is , import targets it with
deploy --preview-name.--deployment - Follow the migrate order every time: optional field → push → backfill → verify → tighten → push; skipping 'optional first' makes the very first push reject existing rows.
- The prod promote needs a fresh explicit yes (deploy-guard) and is a REPEAT of the proven preview run, not a new attempt.
- Keep the prod snapshot as the rollback artifact; state plainly that a snapshot-restore loses data written after the snapshot, so keep the promote window short.
- Treat the exported snapshot as sensitive real data: delete it locally when finished; never commit it.
- Backfills go through @convex-dev/migrations (batched, resumable, dry-runnable), not ad-hoc one-shot mutations over a whole table.
- This is the rehearsal-and-promote flow; for the plain 'explain optional-then-tighten' guidance with no live data, that's migrate.
- 在编辑schema.ts之前,基于变更前的代码创建预览环境并初始化快照——这样导入会符合schema要求,当你推送变更时,一致性校验关卡会在副本(而非生产环境)上失败;每次预览推送使用,导入通过
deploy --preview-name指定目标环境。--deployment - 每次都遵循migrate顺序:可选字段 → 推送 → backfill → 验证 → 收紧规则 → 推送;跳过“先设为可选”会导致第一次推送就拒绝现有行。
- 生产环境推广需要deploy-guard的明确许可,且是重复已验证的预览流程,而非新尝试。
- 保留生产环境快照作为回滚工件;明确说明快照恢复会丢失快照之后写入的数据,因此要缩短推广窗口。
- 将导出的快照视为敏感真实数据:完成后在本地删除;绝不要提交到版本库。
- Backfill通过@convex-dev/migrations(批量、可恢复、可试运行)执行,而非针对整个表的临时一次性变更。
- 这是演练与推广流程;如果是不带真实数据的“先可选后收紧”指导说明,那属于migrate范畴。