Migration Plan
The migration avoids a single high-risk cutover. Writes are introduced first, render artifacts are produced in shadow, and read routing moves only after artifact parity and ACL projection checks are healthy.
Prepare schema and backfill scanner
Add document_versions, render_jobs, access_projection, and idempotency_keys tables. No production behavior changes yet.
Backfill historical versions
Create v1 version rows from current document bodies. Store source hash and mark imported versions as legacy_origin.
Shadow render
Render artifacts for imported versions without serving them. Compare byte size, sanitization decisions, and screenshot checksums.
Internal dogfood
Enable versioned writes and artifact reads for internal workspaces only. Support team reviews trace IDs and state transitions.
Progressive rollout
Enable 5%, then 25%, then 100% of write traffic. Keep read_from_render_artifact independent from write_versioned_documents.
Deprecate mutable body reads
After parity passes and error rate remains below threshold, switch read path to rendered artifacts by default.
Rollback rules
GuardrailDisable read_from_render_artifact if artifact error rate exceeds 0.5% over 10 minutes. Disable enqueue_render_jobs if queue lag exceeds 15 minutes. Keep write_versioned_documents enabled unless data integrity checks fail.
Done criteria
ExitCutover is complete when 99.9% of public reads use immutable artifacts, all new publishes have version rows, duplicate side effects are zero for retry tests, and support can diagnose publish status from trace ID alone.