REST API Soft Delete and Archiving
A user clicks delete by mistake, and the record vanishes forever. Support teams then scramble to restore it from backups. Soft delete prevents this pain. The system marks a record as deleted and hides it, instead of erasing it from the database.
The Recycle Bin Picture
Dragging a file to the recycle bin does not destroy it. The file moves to a holding area where you can restore it. Emptying the bin removes the file for good. Soft delete gives an API the same two-step safety net.
Hard Delete vs Soft Delete
Hard delete: DELETE /notes/5 ──→ row removed from database ──→ gone
Soft delete: DELETE /notes/5 ──→ deletedAt = 2026-11-02T10:00:00Z
row stays, hidden from normal queries
│
├─ restore ──→ deletedAt = null
└─ cleanup job after 30 days ──→ row removed
How It Looks in the API
The client still sends a DELETE request. The server decides how to store the change.
DELETE /notes/5 → 204 No Content GET /notes/5 → 404 Not Found (or 410 Gone) GET /notes → list without note 5
Normal reads hide deleted records. A 410 Gone status tells clients that the record existed and no longer does, which differs from a 404 on an id that never existed.
Restoring Records
Expose a restore action for users who change their minds.
POST /notes/5/restoration
→ 200 OK { "id": "5", "deletedAt": null }
A trash view lists deleted items for review.
GET /notes?status=deleted GET /trash/notes
Limit trash access to the owner or to authorized staff.
Archiving vs Deleting
| Action | Meaning | Visible Where |
|---|---|---|
| Delete | User wants the record gone | Trash view only |
| Archive | User wants it out of the way and kept | Archive view, searchable |
| Hard delete | Permanent removal | Nowhere |
Archiving suits old orders, finished projects, and closed tickets. Model it with a status field such as "status": "archived".
Retention and Permanent Removal
Soft-deleted data cannot stay forever. Privacy laws and user rights often require true erasure. Run a scheduled cleanup that removes records after a set period, such as 30 or 90 days. Offer a permanent delete endpoint for users who request erasure of their data, and make sure backups and search indexes follow the same rule.
Database Details That Matter
- Add a deletedAt column and index it, so filters stay fast.
- Apply the filter in one shared place, such as a base query, so no endpoint forgets it.
- Handle unique fields carefully. A deleted user with email a@x.com can block a new signup with the same email. Use a unique rule that applies only to active rows.
- Decide what happens to child records. Deleting a customer might hide their orders or keep them for accounting.
Cascading Effects
Customer 42 deleted
├── Orders → keep, mark customer as "deleted user"
├── Addresses → hide
└── Sessions → revoke at once
Common Mistakes
Forgetting the Filter
One endpoint that skips the deleted check shows removed data to users. Centralize the filter.
Keeping Personal Data Forever
Soft delete protects against mistakes. It does not satisfy erasure requests. Plan for permanent removal.
Unclear Responses
Document whether repeated DELETE calls return 204 or 404, and apply the rule everywhere.
