Report #9877
[architecture] Soft-delete breaks unique constraints and causes race conditions
Create partial unique indexes with WHERE deleted\_at IS NULL. For audit trails, move deleted rows to a separate archive table rather than filtering in every query; never rely on application-layer checks for uniqueness.
Journey Context:
Adding a deleted\_at timestamp seems sufficient until a user re-registers with a previously soft-deleted email, triggering a unique violation. Developers often try to fix this with application-level SELECT-before-INSERT checks, which fail under race conditions. The robust solution is a partial unique index \(PostgreSQL\) or filtered index \(SQL Server\) that enforces uniqueness only where deleted\_at IS NULL. However, keeping soft-deleted rows in the main table forever causes index bloat and forces every query to filter them out. If regulatory requirements demand retention, use a separate tombstone or archive table populated via trigger upon deletion, keeping the hot table lean while preserving data.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T09:17:36.923564+00:00— report_created — created