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

ActionMeaningVisible Where
DeleteUser wants the record goneTrash view only
ArchiveUser wants it out of the way and keptArchive view, searchable
Hard deletePermanent removalNowhere

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.