用途
convex-migrate-rehearse 用于在 Convex 上安全地演练一次线上应用的 schema 变更与数据回填。Convex 在推送 schema 时会校验每个已有文档是否符合新 schema,任何一行不符合都会导致推送失败——这是一个真实的数据一致性闸门。该技能的做法是让这个闸门先在演练副本上失败,而不是在生产上失败:把预览部署变成生产数据的副本,用生产快照填充,在副本上推送新 schema 并运行回填,观察闸门结果,只有通过后才推广到生产。
主要能力
- 将预览部署作为生产数据的演练副本,用生产快照(snapshot)填充。
- 在副本上按“先可选、后收紧”的顺序推送 schema 变更,让一致性校验在副本上暴露问题。
- 使用 @convex-dev/migrations 执行分批、可恢复、可试运行(dry-run)的回填。
- 在预览上验证迁移后的数据与函数行为。
- 仅在获得明确确认后,把已验证的同一套变更推广到生产。
- 保留生产快照作为回滚产物。
使用方式
工作流如下:
-
前置条件:预览部署需要 Preview Deploy Key(仪表盘 → Project Settings → Deploy Keys → Preview),导出为 CONVEX_DEPLOY_KEY,才能执行 --preview-create/--preview-name 部署;普通的 npx convex login 会话无法创建预览,且这是付费层功能。如果没有预览密钥,退回到用快照填充个人 dev 部署进行演练,并明确说明这一点。
-
守卫:deploy-guard——分类并声明 SOURCE(被读取的生产)和最终 TARGET(被变更的生产);提前获得对生产推广的明确同意并确认计划。
-
只读导出源数据:npx convex export --path snapshot.zip(从持有真实数据的部署执行;仅当迁移涉及文件时才加 --include-file-storage)。这是读取操作,不改变任何内容。
-
从变更前的代码创建预览——在编辑 schema.ts 之前完成,使预览初始 schema 与快照数据一致:npx convex deploy --preview-create migrate-<slug>(需要预览密钥;约 5 天后自动过期)。填充数据:npx convex import snapshot.zip --deployment migrate-<slug>(import 通过 --deployment 按名称指定部署;import 没有 --preview-name 标志)。导入成功是因为数据仍匹配旧 schema。
-
在预览上按 migrate 顺序演练,每次推送为 npx convex deploy --preview-name migrate-<slug>(重新部署到同一预览并保留其数据;不是 convex dev,后者指向个人 dev):(a) 将新增/变更字段设为可选并部署——如果已有行违反它,推送会在此处、在副本上失败并给出问题形状;修复并重新推送直到通过。(b) 编写 @convex-dev/migrations 回填并对预览运行;验证每一行现在都有效。(c) 收紧校验器(required / 收窄 union)并再次部署——此时闸门通过,因为回填已运行。
-
在预览上验证:对迁移后的数据运行应用函数(MCP run/runOneoffQuery 指向预览,或冒烟查询)以确认行为与形状。
-
仅在步骤 1 获得新的明确同意后推广:对生产应用同一序列(可选 schema → 回填 → 收紧)。由于已在生产形状的数据上成功过,生产推送是重复一次已验证的运行。保留快照作为回滚产物(npx convex import snapshot.zip --replace --prod);明确说明快照之后写入的数据会丢失,因此保持推广窗口尽量短。
-
清理:预览会自动过期;完成后删除本地快照(它包含真实数据——视为敏感,绝不提交)。
适用场景
- 需要对线上 Convex 应用执行 schema 变更并回填数据,但希望在副本上先验证一致性。
- 需要让 Convex 的数据一致性校验在预览上暴露问题,而不是在生产上失败。
- 需要分批、可恢复的回填,而非一次性全表 mutation。
限制
- 预览部署需要 Preview Deploy Key,且属于付费层功能;没有预览密钥时只能退回个人 dev 部署演练。
- 预览约 5 天后自动过期。
- 快照恢复会丢失快照之后写入的数据,因此推广窗口应保持短。
- 导出的快照包含真实数据,属于敏感信息,完成后应本地删除且绝不提交。
- 生产推广需要新的明确同意,且是已验证预览运行的重复,而非新的尝试。
- 回填必须通过 @convex-dev/migrations 进行,不能使用针对整表的临时一次性 mutation。