Hazards
Every step carries a set of hazards. plan and apply refuse (exit code 3) to emit or run a plan that contains any hazard unless --allow-hazards is given. The refusal lists each hazardous step.
| Hazard | Meaning | Examples |
|---|---|---|
DATA_LOSS |
Existing data is destroyed or may be truncated/rejected | DROP TABLE, DROP COLUMN, narrowing a type (varchar(20) to varchar(10), bigint to integer, text to varchar(n), lower numeric precision), recreating a plain column as a generated one, SQLite rebuild that drops a column |
LOCKING (estimate) |
Takes a lock that blocks reads/writes for a time proportional to table size | ALTER COLUMN TYPE (ACCESS EXCLUSIVE during the rewrite), adding a column with a volatile default or a stored generated column |
REWRITE |
The whole table is rewritten | ALTER COLUMN TYPE that is not binary-compatible, adding a column with a volatile default (gen_random_uuid(), random(), nextval()), every SQLite table rebuild |
IRREVERSIBLE |
The down migration restores structure but not the data | DROP TABLE, DROP COLUMN |
What is deliberately not a hazard
These use the safe online patterns instead (see planner):
- new indexes (
CONCURRENTLY), dropped indexes (CONCURRENTLY), - new foreign keys and checks (
NOT VALIDthenVALIDATE), SET NOT NULL(validated check first),- new unique/primary-key constraints (concurrent unique index, then
USING INDEX), - widening
varchar(n),varchartotext, increasingnumericprecision at equal scale (no rewrite), - adding a nullable column or one with a constant default (PostgreSQL 11+ stores it in the catalog),
- adding enum values.
Type-change classification (PostgreSQL)
| From to | Hazards |
|---|---|
varchar(10) to varchar(20), varchar(n) to text |
none |
varchar(20) to varchar(10), text to varchar(n) |
LOCKING, REWRITE, DATA_LOSS |
integer to bigint |
LOCKING, REWRITE |
bigint to integer |
LOCKING, REWRITE, DATA_LOSS |
numeric(10,2) to numeric(12,2) |
none |
numeric(10,2) to numeric(8,2) |
LOCKING, REWRITE, DATA_LOSS |
| anything else | LOCKING, REWRITE |
Warnings
Some problems depend on data, so they are warnings printed with the plan (and as -- warning: lines in the file) instead of hazards: adding a NOT NULL column without a default, a column becoming NOT NULL in a SQLite rebuild without a default.
Failure behavior
SQLite: one transaction; any statement error or foreign_key_check violation rolls everything back. PostgreSQL: steps are committed one by one, so a failure (for example VALIDATE CONSTRAINT finding violating rows) leaves earlier steps applied; fix the data and run apply again, the new plan contains only what is left.