Overview
Soft delete allows you to mark records as deleted without permanently removing them from the database. This is useful for:- Maintaining data history
- Implementing “trash” functionality
- Audit trails and compliance
- Recovering accidentally deleted records
Setup
Entity Configuration
Add adeletedAt column to your entity:
user.entity.ts
The
@DeleteDateColumn() decorator from TypeORM automatically handles soft delete timestamps.Controller Configuration
Enable soft delete in your controller:users.controller.ts
How It Works
When soft delete is enabled:Delete Operation
Request:- Sets
deletedAtto current timestamp - Record remains in database
- Record is excluded from normal queries
Query Behavior
By default, soft-deleted records are excluded: Request:- Returns only records where
deletedAt IS NULL - Soft-deleted records are hidden
Including Deleted Records
Use theincludeDeleted query parameter:
Request:
- Returns all records, including soft-deleted ones
- Useful for showing “trash” views
Recovery Endpoint
TherecoverOne endpoint restores soft-deleted records:
Request:
- Sets
deletedAttonull - Record becomes visible in normal queries again
Configure Recovery Response
Control whether to return the recovered entity:users.controller.ts
Global Configuration
Enable soft delete globally for all controllers:main.ts
Complete Example
Here’s a full implementation:Entity
company.entity.ts
Controller
companies.controller.ts
Service
companies.service.ts
Usage Examples
Soft Delete a Company
List Active Companies
deletedAt IS NULL.
List All Companies (Including Deleted)
Filter Deleted Companies Only
Recover a Company
With Relationships
Soft delete works with relationships:Cascade Soft Delete
To soft delete related entities, configure cascades in your entity:company.entity.ts
Disabling Specific Routes
You can disable the recover route if not needed:Swagger Documentation
When soft delete is enabled, Swagger automatically documents:includeDeletedquery parameter ongetManyandgetOnePATCH /:id/recoverendpoint for recoverydeletedAtfield in entity schemas
Hard Delete
To permanently delete records, implement a custom method:users.controller.ts
users.service.ts
Best Practices
1
Use DeleteDateColumn
Always use TypeORM’s
@DeleteDateColumn() decorator for consistency.2
Index deletedAt
Add an index to
deletedAt for better query performance.3
Audit Trail
Combine with
@CreateDateColumn() and @UpdateDateColumn() for complete audit trails.4
Cleanup Strategy
Implement a cleanup job to hard delete old soft-deleted records if needed.
Database Migration
Add soft delete to existing tables:Troubleshooting
Records Not Being Soft Deleted
Ensure:- Entity has
@DeleteDateColumn()decorator softDelete: trueis set in query options- Service extends
TypeOrmCrudService
Deleted Records Still Appearing
Check:includeDeletedparameter isn’t being set- Query filters aren’t overriding soft delete behavior
- Database column exists and is nullable
Related Resources
- Query Options - Learn about query configuration
- Routes - Configure route options
- Global Configuration - Set global soft delete settings