Skip to main content

ADR-0010: Migrations Stay Additive; Rollback Is by Flag, Not by Schema Reversion

Status

Accepted

Context

A migration that drops a column on downgrade() destroys data. If a deploy is rolled back to an earlier code version after that migration ran, rolling back the schema too would permanently lose whatever was written to that column in the meantime — data that reverting the code alone does not bring back.

Decision

downgrade() deliberately raises NotImplementedError in every migration. Schema changes are additive only. Behavior instead reverts through environment-variable flags (FANOUT_V2, STREAM_AUTHZ_ENFORCE) — every staged rollout is required to revert by flipping a flag, not by requiring a redeploy or a schema reversion.

Alternatives Considered

Not recorded in source material.

Consequences

  • A code rollback (deploying an older git tag) never needs a matching schema rollback — the database is always compatible with an older application version, because nothing destructive ever runs on downgrade.
  • Any behavior change risky enough to need a rollback path must be designed as a flag-gated rollout from the start (see ADR-0007 and ADR-0008) — this ADR is the general rule those two are specific instances of.
  • Schema growth is one-directional: old columns/tables that become unused stay in place rather than being dropped as part of a reversible process: removing them is a separate, deliberate forward migration, not something downgrade ever automates.