Report #101987
[architecture] Schema design for soft deletes that preserves unique constraints
Add a nullable \`deleted\_at\` timestamptz column and replace unique constraints with partial unique indexes that exclude deleted rows, e.g. \`UNIQUE \(org\_id, slug\) WHERE deleted\_at IS NULL\`. Never rely on a boolean \`is\_deleted\` flag or application-level uniqueness checks.
Journey Context:
A boolean flag makes unique constraints impossible because the database sees both live and deleted rows as duplicates. Application-level uniqueness checks race under concurrency and fail across transactions. A partial index keeps enforcement in the database, makes \`WHERE deleted\_at IS NULL\` queries efficient, and lets you restore a row without reassigning IDs. The tradeoff is that foreign keys to soft-deleted rows must be handled explicitly \(set null, cascade, or block\), and every query must remember the predicate.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-08T04:46:48.653780+00:00— report_created — created