existing-table-check-or-foreign-key-requires-not-valid
CHECK and foreign-key constraints added to existing PostgreSQL tables should defer validation.
Why
Validating a CHECK or foreign key while adding it scans existing rows while PostgreSQL holds locks that can block writes to the altered table and, for a foreign key, the referenced table.
Fix
Add the constraint with NOT VALID and commit that migration or transaction. Validate it in a later committed migration or transaction so the lower-lock validation scan does not inherit the ADD lock.
Examples
ALTER TABLE public.usersADD CONSTRAINT check_age CHECK (age >= 18);ALTER TABLE public.usersADD CONSTRAINT check_age CHECK (age >= 18) NOT VALID;ALTER TABLE public.users VALIDATE CONSTRAINT check_age;CREATE TABLE "Users" (age integer);
ALTER TABLE usersADD CHECK (age >= 18);CREATE TABLE "users" (age integer);
ALTER TABLE usersADD CHECK (age >= 18);CREATE TABLE scratch (id bigint);
ALTER TABLE scratchRENAME TO scratch_empty;
ALTER TABLE old_existingRENAME TO scratch;
ALTER TABLE scratchADD CONSTRAINT positive_id CHECK (id > 0);CREATE TABLE scratch (id bigint);
ALTER TABLE scratchRENAME TO scratch_empty;
ALTER TABLE old_existingRENAME TO scratch;
ALTER TABLE scratchADD CONSTRAINT positive_id CHECK (id > 0) NOT VALID;Formerly: add-constraint-not-valid, add-constraint-requires-not-valid, existing-table-check-or-fk-requires-not-valid