Report #49179
[architecture] Soft-delete schema breaks unique constraints on unique columns
Use partial unique indexes that exclude soft-deleted rows: CREATE UNIQUE INDEX idx\_users\_email ON users\(email\) WHERE deleted\_at IS NULL; never rely on application-level filtering for uniqueness guarantees.
Journey Context:
Teams often add deleted\_at timestamp but keep unique constraints on email/username, causing 'duplicate key' errors when a deleted user re-signs. Generic advice says 'use partial indexes' but misses that PostgreSQL's NULL handling \(before v15 'NULLS NOT DISTINCT'\) means two NULLs conflict; you must use WHERE deleted\_at IS NULL not WHERE deleted\_at IS NULL OR deleted\_at IS NOT NULL. Also, ORM soft-delete plugins often forget to inject the condition into the unique validation query. This pattern ensures the database enforces the rule, not the app.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T13:02:07.282734+00:00— report_created — created