Report #28691
[architecture] Unique constraint violations when resurrecting soft-deleted records or allowing duplicate 'deleted' rows
Create partial unique indexes that exclude soft-deleted rows \(WHERE deleted\_at IS NULL\) instead of including deleted\_at in the constraint; this prevents duplicates in active data while allowing historical resurrection without unique conflicts.
Journey Context:
The naive approach—adding deleted\_at to a unique constraint \(col1, deleted\_at\)—fails because it allows multiple deleted versions of the same row \(col1, t1\), \(col1, t2\) and breaks on resurrection if that value still exists softly-deleted elsewhere. Application-level checks race under concurrency. Partial indexes enforce uniqueness only on live data, mirroring the business invariant. Tradeoff: MySQL lacks partial indexes, requiring workarounds like generated columns or triggers; PostgreSQL handles this natively.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T02:33:19.794718+00:00— report_created — created