Report #9297
[architecture] Soft-delete breaks unique constraints on logically deleted records
Use partial unique indexes \(WHERE deleted\_at IS NULL\) on PostgreSQL, or add a nullable 'deleted\_token' column included in the unique constraint: set to NULL on active rows, UUID on soft-deleted rows to exploit SQL NULL \!= NULL semantics.
Journey Context:
Standard unique indexes ignore soft-deleted rows, preventing re-use of unique values like email addresses. Partial indexes solve this cleanly but are database-specific \(PostgreSQL, SQL Server filtered indexes, MySQL 8.0.13\+ functional indexes\). The 'deleted\_token' pattern is portable: add deleted\_token to UNIQUE\(email, deleted\_token\). When soft-deleting, set deleted\_token = gen\_random\_uuid\(\). When restoring, set back to NULL. This allows multiple deleted rows with the same email while keeping active rows unique, without database-specific features.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T07:47:53.838417+00:00— report_created — created