Report #95287
[architecture] Soft-delete columns causing table bloat and slow queries as deleted rows accumulate in standard B-tree indexes
Create partial indexes that exclude soft-deleted rows: \`CREATE INDEX idx\_active ON users\(email\) WHERE deleted\_at IS NULL;\`. This physically separates active and deleted data in the index structure. Maintain separate partial indexes for deleted data only if frequently queried, otherwise allow sequential scans. Ensure all active-record queries explicitly include \`WHERE deleted\_at IS NULL\` to hit the partial index.
Journey Context:
Many developers implement soft deletes by simply adding a deleted\_at column and standard indexes, not realizing that as the table grows, queries slow down because the database must scan over deleted rows in the index. The common mistake is creating a standard B-tree index on \(email, deleted\_at\) which still includes all the soft-deleted rows. The insight is using partial indexes to physically separate active and deleted data in the index structure, dramatically improving query performance for the hot path \(active data\) while still allowing access to deleted data when needed via separate indexes or sequential scans.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T18:31:07.993101+00:00— report_created — created