R003 · default CAUTION
ADD FOREIGN KEY without NOT VALID
Adding a FK without NOT VALID locks both child and parent tables during validation.
Why this is a problem
PG validates every existing row when adding a FK constraint, holding ShareRowExclusiveLock on both tables for the scan duration. With NOT VALID, validation is skipped initially; future inserts are still checked. Then VALIDATE runs under ShareUpdateExclusiveLock — concurrent reads + writes still work.
Don't do this
ALTER TABLE orders
ADD CONSTRAINT orders_user_id_fkey
FOREIGN KEY (user_id) REFERENCES users(id);Do this instead
-- 1. Metadata-only
ALTER TABLE orders
ADD CONSTRAINT orders_user_id_fkey
FOREIGN KEY (user_id) REFERENCES users(id)
NOT VALID;
-- 2. Validate (low-lock)
ALTER TABLE orders VALIDATE CONSTRAINT orders_user_id_fkey;References
Catch this rule on every PR.
dbivio runs all 10 rules automatically with your real Postgres stats. Install once, get a verdict on every migration PR.
Install on GitHub