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

工作流程

  1. PRECONDITION: preview deployments need a Preview Deploy Key (dashboard → Project Settings → Deploy Keys → Preview) exported as
    CONVEX_DEPLOY_KEY
    before any
    --preview-create
    /
    --preview-name
    deploy — a plain
    npx convex login
    session 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.
  2. 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.
  3. SNAPSHOT the source data read-only:
    npx convex export --path snapshot.zip
    (from the deployment holding the real data; add
    --include-file-storage
    only if the migration touches files). This is a read; it changes nothing.
  4. 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:
    npx convex deploy --preview-create migrate-<slug>
    (needs the preview key; auto-expires ~5 days). Seed it:
    npx convex import snapshot.zip --deployment migrate-<slug>
    (import targets a deployment by NAME with
    --deployment
    ; there is no
    --preview-name
    flag on import). The import succeeds because the data still matches the old schema.
  5. REHEARSE on the preview, in the migrate order — each push is
    npx convex deploy --preview-name migrate-<slug>
    (re-deploys to the SAME preview, keeping its data; NOT
    convex dev
    , 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.
  6. VERIFY on the preview: run the app's functions against the migrated data (MCP
    run
    /
    runOneoffQuery
    pointed at the preview, or a smoke query) to confirm behavior and shape.
  7. 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 (
    npx convex import snapshot.zip --replace --prod
    ); state plainly that data written after the snapshot is lost, so keep the promote window short.
  8. CLEAN UP: the preview auto-expires; delete the local snapshot when done (it holds real data — treat it as sensitive, never commit it).
  1. 前提条件:在执行任何
    --preview-create
    /
    --preview-name
    部署前,预览部署环境需要一个预览部署密钥(控制台 → 项目设置 → 部署密钥 → 预览),并导出为
    CONVEX_DEPLOY_KEY
    ——普通的
    npx convex login
    会话无法创建预览环境,且这是付费层级功能。如果没有可用的预览密钥,则退回到在由快照初始化的个人开发部署环境中进行演练,并告知相关情况。
  2. 校验:deploy-guard —— 分类并告知源环境(正在读取的生产环境)和最终目标环境(即将变更的生产环境);提前获取生产环境推广的明确许可,并确认计划。
  3. 只读快照源数据:
    npx convex export --path snapshot.zip
    (从存储真实数据的部署环境执行;仅当迁移涉及文件时添加
    --include-file-storage
    )。这是只读操作,不会改变任何内容。
  4. 基于变更前的代码创建预览环境——在编辑schema.ts之前完成此操作,这样预览环境启动时使用的schema与快照数据已有的schema一致:
    npx convex deploy --preview-create migrate-<slug>
    (需要预览密钥;约5天后自动过期)。初始化预览环境:
    npx convex import snapshot.zip --deployment migrate-<slug>
    (导入通过
    --deployment
    指定目标部署环境;import没有
    --preview-name
    参数)。由于数据仍与旧schema匹配,导入会成功。
  5. 在预览环境中按migrate顺序进行演练——每次推送使用
    npx convex deploy --preview-name migrate-<slug>
    (重新部署到同一个预览环境,保留其数据;而非
    convex dev
    ,后者针对个人开发环境):(a) 将新增/修改的字段设为OPTIONAL并推送——如果现有行违反该设置,推送会在此副本上失败,显示有问题的数据结构;修复后重新推送直到验证通过。(b) 编写一个@convex-dev/migrations backfill并在预览环境中运行;验证每一行现在都有效。(c) 收紧校验规则(设为必填/缩小联合类型范围)并再次推送——由于已运行backfill,校验关卡现在会通过。
  6. 在预览环境中验证:针对迁移后的数据运行应用的函数(指向预览环境的MCP
    run
    /
    runOneoffQuery
    ,或冒烟查询),确认行为和数据结构。
  7. 仅在步骤1获得的明确许可下进行推广:将相同的步骤应用到生产环境(可选schema → backfill → 收紧规则)。由于该流程已在与生产环境一致的数据上成功执行,生产环境的推送是重复已验证的流程。保留快照作为回滚工件(
    npx convex import snapshot.zip --replace --prod
    );明确说明快照恢复会丢失快照之后写入的数据,因此要缩短推广窗口。
  8. 清理:预览环境会自动过期;完成后删除本地快照(它包含真实数据——视为敏感数据,绝不要提交到版本库)。

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
    deploy --preview-name
    , import targets it with
    --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范畴。