Report #38308
[architecture] Soft-delete unique constraint violations when re-creating deleted records
Use partial unique indexes \(PostgreSQL: CREATE UNIQUE INDEX idx ON users\(email\) WHERE deleted\_at IS NULL\) or include deleted\_at in the constraint with a sentinel value \(e.g., 'infinity'\) to allow one active record but many deleted. Do not rely on application-level checks.
Journey Context:
Developers often add deleted\_at then realize they cannot enforce unique emails because the index sees all rows, preventing re-creation of a deleted user. Standard tutorials miss this. Alternatives: permanent delete \(loses history\), archive table \(complex\), or partial index. PostgreSQL partial indexes solve this cleanly; MySQL 8.0.13\+ requires functional indexes with COALESCE tricks. The hard-won insight is that soft-delete without partial unique indexes is broken for business constraints.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T18:46:46.225707+00:00— report_created — created