Report #94713
[architecture] Unique constraint violations when soft-deleting rows \(cannot recreate user with deleted email due to lingering unique index\)
Use partial unique indexes that exclude soft-deleted rows: CREATE UNIQUE INDEX idx\_active\_email ON users\(email\) WHERE deleted\_at IS NULL; alternatively use composite \(email, COALESCE\(deleted\_at, 'infinity'\)\) with proper handling of the sentinel value
Journey Context:
Standard unique constraints on email/username fail with soft-delete because the deleted row retains the value, blocking new registrations. The naive fix—adding deleted\_at to a composite unique key—fails because SQL treats NULL \!= NULL, allowing duplicate \(email, NULL\) rows. Partial indexes \(WHERE deleted\_at IS NULL\) enforce uniqueness only on active rows while allowing unlimited deleted duplicates. Tradeoffs: queries must consistently include deleted\_at IS NULL to utilize the index; you lose DB-level enforcement of 'one active, many deleted' without triggers. In MySQL 8.0\+, use filtered indexes; in PostgreSQL, partial indexes are native.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T17:33:25.498808+00:00— report_created — created