PostgreSQL 18 · first-party documentation guide

PostgreSQL NOT VALID: why old invalid rows can remain

If adding the constraint succeeded but old invalid rows remain, check whether the constraint was added NOT VALID.
PostgreSQL NOT VALID: why old invalid rows can remain
Constraint added ≠ historical rows validated.NOT VALID can skip validation of existing rows.NOT VALID is not NOT ENFORCED.

If adding the constraint succeeded but old invalid rows remain, check whether the constraint was added NOT VALID.

Start with the symptom

If adding the constraint succeeded but old invalid rows remain, check whether the constraint was added NOT VALID.

What the documentation establishes

In PostgreSQL 18, adding a foreign-key or CHECK constraint NOT VALID can skip scanning existing rows.

The constraint is not simply disabled: subsequent INSERT and UPDATE operations are still checked.

Five checks at a glance

ScenePointLimit
1Constraint added ≠ historical rows validated.Constraint deployment success is not historical validation.
2NOT VALID can skip validation of existing rows.This documented shortcut applies to foreign-key and CHECK constraints.
3NOT VALID is not NOT ENFORCED.NOT VALID ≠ NOT ENFORCED
4Historical validation is a separate operation.VALIDATE CONSTRAINT is the separate historical-row check.
5Treat deployment and historical validation as separate evidence.No production SQL or lock-duration test was performed.

Do not over-interpret the symptom

Validating historical rows is a separate VALIDATE CONSTRAINT step. The documentation describes a separate lock level for this validation.

Read-only preflight

Evidence limits

Do not equate successful constraint deployment with completed historical validation. No production SQL or lock timing was tested.

This article interprets first-party documentation and uses hypothetical diagrams. It does not report a live device, database, customer-data, outage, recovery or performance test.

Watch the short explanation

YouTube channel

The public YouTube schedule may be linked here after the provider assigns the native video ID. The article and local video are already self-contained.