← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Soft Delete Pattern

database Intermediate

Also Known As

soft delete MySQL deleted_at pattern logical delete paranoid delete

TL;DR

Marking records as deleted with a deleted_at timestamp instead of physically removing them — preserving data for auditing and recovery.

Explanation

Soft delete adds a nullable DATETIME column (commonly deleted_at or is_deleted). All queries filter WHERE deleted_at IS NULL to exclude deleted records. Advantages: data recovery, audit trail, referential integrity preservation. Disadvantages: all queries need the filter, indexes are less efficient as soft-deleted rows accumulate, unique constraints must account for soft-deleted duplicates. Hard deleting after a retention period (archiving) is common.

Common Misconception

Soft delete solves the data recovery problem completely. Without a cleanup/archive strategy, soft-deleted rows accumulate indefinitely, degrading query performance and bloating the table.

Why It Matters

Physical DELETE is irreversible. Soft delete gives you recovery capability and audit history — critical for user data, financial records, and compliance.

Common Mistakes

  • Forgetting the WHERE deleted_at IS NULL filter in some queries — returning deleted records.
  • Unique constraints broken by soft-deleted duplicates — a deleted email re-registered violates UNIQUE.
  • Not archiving old soft-deleted rows — table size grows indefinitely.

Avoid When

  • Avoid soft delete for high-volume append-only data (logs, events) — deleted rows accumulate and degrade performance.
  • Do not use soft delete without a cleanup/archive strategy — tables grow indefinitely.

When To Use

  • Use soft delete for user data, financial records, and any content requiring audit trails or recovery.
  • Use soft delete when related records reference the row via foreign keys — hard delete would violate referential integrity.

Code Examples

✗ Vulnerable
-- Hard delete — irreversible, breaks foreign keys, loses history
DELETE FROM users WHERE id = ?;
✓ Fixed
-- Schema
ALTER TABLE users ADD COLUMN deleted_at DATETIME NULL DEFAULT NULL;
CREATE INDEX idx_users_deleted ON users (deleted_at);

-- Soft delete
UPDATE users SET deleted_at = NOW() WHERE id = ?;

-- All queries filter deleted
SELECT * FROM users WHERE deleted_at IS NULL;

// PHP: unique email workaround for soft-deleted
$stmt = $pdo->prepare(
    'SELECT id FROM users WHERE email = ? AND deleted_at IS NULL'
);

Added 31 Mar 2026
Views 28
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 2 pings M 1 ping T 1 ping W 2 pings T 2 pings F 0 pings S 2 pings S 0 pings M 0 pings T 1 ping W 0 pings T
No pings yet today
ChatGPT 11 Perplexity 5 Google 5 Unknown AI 3 Meta AI 1 Ahrefs 1
crawler 25 pre-tracking 1
DEV INTEL Tools & Severity
⚙ Fix effort: Low
⚡ Quick Fix
Add deleted_at DATETIME NULL DEFAULT NULL to tables and filter WHERE deleted_at IS NULL in all SELECT/UPDATE queries
📦 Applies To
web cli
🔗 Prerequisites
🔍 Detection Hints
DELETE FROM users WHERE id = ? without soft delete consideration
Auto-detectable: ✗ No
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: High Context: File Tests: Regenerate

✓ schema.org compliant