Report #16657
[architecture] Soft-delete breaks unique constraints \(e.g., email uniqueness\)
Use a partial unique index that excludes soft-deleted rows \(e.g., CREATE UNIQUE INDEX idx\_email ON users\(email\) WHERE deleted\_at IS NULL\) rather than adding deleted\_at to the constraint. This allows the email to be reused after hard deletion without schema changes.
Journey Context:
Developers often add a deleted\_at timestamp and don't realize the existing UNIQUE\(email\) constraint now prevents re-registration of a deleted account. Adding deleted\_at to the constraint \(email, deleted\_at\) seems like a fix but permanently blocks email reuse even after hard delete unless you use a sentinel value or UUID for non-deleted rows. The partial index approach is Postgres-specific but operationally clean; for MySQL \(which lacks partial indexes\), you must use a separate 'deleted\_users' table or a nullable 'email' column that is nulled on soft-delete, breaking the constraint logic. The partial index maintains performance and integrity without application-level locking.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T03:15:54.627180+00:00— report_created — created