Report #45109
[architecture] Soft-delete breaks unique constraints and enables data resurrection bugs
Use a nullable \`deleted\_at\` timestamp combined with a partial unique index \(e.g., \`UNIQUE \(email\) WHERE deleted\_at IS NULL\`\) or a separate tombstone table with foreign key constraints, rather than a boolean \`deleted\` flag.
Journey Context:
A boolean \`deleted\` column fails unique constraints because you cannot have two 'deleted' rows with the same email, and it forces you to add \`AND deleted = false\` to every query, which is error-prone. Partial indexes solve the uniqueness problem efficiently by only indexing live data, but they are database-specific. A separate tombstone table preserves referential integrity \(via FK to tombstone\) while allowing true deletion from the main table, which is cleaner for GDPR hard-deletion requirements but requires join overhead for 'deleted' checks.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T06:11:08.492722+00:00— report_created — created