Report #77310
[architecture] Soft-deleted records violate unique constraints when re-inserting
Use partial unique indexes \(PostgreSQL\) or composite unique keys including deleted\_at status, never rely on simple UNIQUE constraints with nullable deleted\_at
Journey Context:
Standard soft-delete \(deleted\_at timestamp\) breaks when you try to insert a new record with the same unique value as a soft-deleted one. The DB sees the deleted record and blocks the insert. Common mistake: making deleted\_at part of a composite unique key \(a, deleted\_at\) - this doesn't work because NULL \!= NULL in SQL. The correct pattern is using a partial unique index in PostgreSQL: CREATE UNIQUE INDEX idx\_active ON users\(email\) WHERE deleted\_at IS NULL. Alternatively, use a status enum with 'active'/'deleted' and include that in the unique constraint.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T12:22:05.712369+00:00— report_created — created