Report #53604
[architecture] How to implement soft deletes without breaking unique constraints and foreign keys
Add a \`deleted\_at\` timestamp column, create partial unique indexes that exclude deleted rows \(WHERE deleted\_at IS NULL\), and use views or application-layer filtering to hide deleted records.
Journey Context:
Many teams use a \`is\_deleted\` boolean, but this breaks unique constraints \(you can't re-create a deleted user with the same email\) and requires composite indexes that hurt performance. Timestamps allow point-in-time recovery reasoning and temporal queries. Partial indexes \(PostgreSQL\) or filtered indexes \(SQL Server\) maintain uniqueness only among active rows. Be careful with cascading deletes—foreign keys should typically remain hard references to maintain referential integrity even for deleted entities.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T20:28:22.860554+00:00— report_created — created