| name | reviewing-migration-and-data-safety |
| description | Reviews schema migrations and data changes for safety: backward compatibility with the running app (expand/migrate/contract), table locks from NOT NULL/index/FK on large tables, unbatched backfills, missing dual-write during transitions, irreversible or destructive DDL, and integrity constraints left to app code. Use when reviewing migrations, ALTER TABLE, backfills, schema or data-format changes, or anything touching persistence. Skip when the change touches no schema, migration, backfill, or persisted data format โ pure in-memory or stateless logic with no durable store behind it. |
| provenance | {"taxonomy_version":"v0.9","built_from":[{"category":20,"source":"docs/research/cluster-5-verification.md#20","hash":"785fbe4991e7f9d964b703103d96b991c4b676607b30a744f5270de179f41644"}]} |
reviewing-migration-and-data-safety
Can this migration lock tables or lose data? Expand/contract, backfills, reversibility.
When to use
Reviews schema migrations and data changes for safety: backward compatibility with the running app (expand/migrate/contract), table locks from NOT NULL/index/FK on large tables, unbatched backfills, missing dual-write during transitions, irreversible or destructive DDL, and integrity constraints left to app code. Use when reviewing migrations, ALTER TABLE, backfills, schema or data-format changes, or anything touching persistence. Skip when the change touches no schema, migration, backfill, or persisted data format โ pure in-memory or stateless logic with no durable store behind it.
Shape: diff โ design-capable. Also works on design docs and plans: apply the same checks to the proposed states, data flows, and failure paths before any code exists. When the design doc is specifically a decision record (an ADR, RFC, or adoption/deprecation plan), also run the shared decision-record checklist on top of this lens's own topical checks: is the rationale actually recorded (not just the outcome); are the stated assumptions still current; is there a revisit-trigger; is an exit, rollback, or sunset path defined; were real alternatives weighed, not just the chosen option justified after the fact? A gap here is this lens's finding, reported the same way as a topical one โ not a separate report.
Reviewer discipline
Report only real problems. If the code correctly handles the case, reply "No findings" and stop โ do not invent issues. This guards against false positives on correct code; still report every genuine issue you do find, with its full detail.
Defects are the default; improvements are opt-in. By default this lens is defect-only: do not suggest changes to code that is already correct. When the team has opted up into improvement suggestions, a finding on already-correct code is admissible only as nit-severity, route: implementer (the author applies, defers, or ignores), and must clear the non-configurable anti-churn floor: it must genuinely improve โ never offer a merely equivalent alternative โ and must converge (once a dimension is as good as you can confidently make it, stop; never oscillate AโB then BโA, never re-order to an equivalent state). Defects keep the strict bar above regardless of this setting.
Team preferences. If the reviewed repo has .code-quality-atlas/preferences.md, apply it before reporting: a repo's .code-quality-atlas/preferences.md may set/tune this lens's thresholds or selection, but this is a floor-tier lens: it can never suppress a finding outright. The strongest override available is acknowledge โ a recorded rationale that keeps the finding visible, tagged acknowledged deviation: <reason>, and non-blocking rather than removing it. Absent the file, apply this lens's defaults exactly as written above.
Pre-existing defects in touched code are surfaceable, not yours to fix. When you notice a genuine defect this change did not introduce but that sits in the code this PR actually touches โ the edited function or immediately adjacent lines โ you may surface it, tagged "pre-existing โ not introduced by this change." Like improvements it is opt-in and default-quiet (off unless the team opts up), route: implementer, and non-blocking: it informs the author's fix-now / file-a-ticket / ignore call and never sets this PR's verdict, because the diff did not cause it. Stay scoped to code the change touches โ a repo-wide hunt is the audits' job, not this review โ and never let it expand the PR's scope.
Top checks
The head of the full checklist โ enough for a first pass without opening any reference file:
- Is the schema change backward-compatible with the currently-running app version (rolling deploy)? If breaking, is it split expandโmigrateโcontract?
- Does adding a NOT NULL column / index / FK lock the table (esp. large tables)? Use safe variants (
CREATE INDEX CONCURRENTLY; add nullable then backfill; NOT VALID then validate).
- Is a data backfill batched, throttled, idempotent, and resumable โ not one giant
UPDATE?
- During the transition, does the app dual-write/dual-read so neither old nor new code breaks?
- Are migrations reversible โ or is the irreversibility deliberate and documented?
- Are integrity constraints (FK, UNIQUE, CHECK, NOT NULL) used so the DB enforces invariants, not just app code (cross #10)?
- Are transaction boundaries correct โ multi-step writes atomic, no partial commit on failure (cross #2)?
- Is destructive DDL (DROP column/table) gated until the new path is verified live and old code drained?
Mechanizing these checks
Where a finding here is one a tool can catch deterministically, surface that as an advisory route: implementer note next to the finding: the hand review caught it this time, and wiring the matching tool from reference/tool-rules.md into CI gates it going forward. This is a suggestion to mechanize, not a defect โ it never blocks a verdict, and it falls away on a repo that already runs the tool.
Process notes. If this lens misfired on this change โ flagged correct code, missed an obvious issue squarely in its own scope, or its checklist didn't fit the change shape โ say so in one line under synthesizing-review-findings's Process notes appendix; that is not a defect finding. Say nothing if the lens worked as intended โ never invent a process note to fill the section.
Going deeper
- reference/heuristics.md โ the full checklist; open it when the change sits squarely in this lens's domain.
- examples.md โ concrete good/bad findings, and the output format to match.
- reference/tool-rules.md โ static-analysis rules covering the mechanical subset; for wiring up linters, not needed for the judgment review itself.
- reference/sources.md โ the research behind each check; for provenance, not needed during a review.