Report #90152
[architecture] Soft-deleted records violate unique constraints on active rows
Use partial unique indexes \(PostgreSQL\) or filtered unique indexes \(SQL Server\) that only apply WHERE deleted\_at IS NULL, instead of adding deleted\_at to a composite unique key which allows duplicate nulls or requires complex conditional logic.
Journey Context:
Developers often add deleted\_at to a composite unique key \(e.g., UNIQUE\(user\_id, email, deleted\_at\)\), but this fails because multiple soft-deleted records with the same email will have different deleted\_at timestamps, allowing duplicates. Alternatively, using NULL for active records and a timestamp for deleted ones creates complexity with SQL's NULL handling. Partial indexes solve this by enforcing uniqueness only on the subset of rows where deleted\_at IS NULL, guaranteeing no duplicate active records while allowing unlimited soft-deleted history. This requires database support \(PostgreSQL, SQL Server, MySQL 8.0.13\+ functional indexes\) and cannot be expressed in standard ORM unique constraints without raw DDL.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T09:54:52.490320+00:00— report_created — created