Straight answer: a normal delete is reversible for a limited window because the record sits in the recycle bin keeping its ID. A hard delete is not reversible by you at all. At scale the danger is rarely the delete you intended. It is the cascade you did not model, so the safe procedure is always to count the children first, delete in child-to-parent order, and keep hard delete for data you have just loaded incorrectly.
What delete actually does
Deleting flips IsDeleted to true and moves the record to the recycle bin. It keeps its ID, it still occupies storage, and it disappears from every ordinary query. You can still see it:
SELECT Id, Name, IsDeleted, LastModifiedDate
FROM Account
WHERE CreatedDate = LAST_N_DAYS:30
AND IsDeleted = true
ALL ROWS
The bin holds records for 15 days, with a capacity tied to your org’s data storage. When the capacity is reached, the oldest records are purged early. So 15 days is a ceiling, not a promise, and on a large deletion run you can lose the ability to undelete within hours.
Cascade is where the surprises live
Deleting a parent removes more than the parent:
- Master-detail children are always deleted with the master. There is no option.
- Lookup children follow whatever the relationship’s delete behaviour says: clear the field, block the delete, or cascade. Check each one. The default is not always what you assume.
- Standard relationships cascade too. Deleting an account takes its contacts, opportunities and cases with it.
- Attached records. Notes, files, activities and shares attached to anything deleted go as well.
Two things to verify rather than assume. Cascade deletes do not respect the child object’s delete permission for the running user, so a user who cannot delete cases can still remove them by deleting the account. And do not assume your child-object delete trigger fires for a cascaded record. Test that specific path in a sandbox before you rely on it for cleanup logic.
Count before you delete. One aggregate query per child object, for the parents you are about to remove, is five minutes that has saved a great many weekends.
Hard delete
Hard delete skips the bin entirely. Two routes:
Database.emptyRecycleBin(recordsOrIds);
and the Bulk API hard delete operation, which needs the Bulk API Hard Delete permission on the user. That permission is not on any standard profile by default, which is deliberate. Keep it that way and grant it through a permission set for the duration of the job.
Hard delete has one honest use case: you have just loaded a few hundred thousand wrong records and you want them gone without filling the bin and purging real data early. Use it for that. Do not use it as a routine archive step.
What you cannot get back
- Anything hard-deleted, or purged from the bin after the window.
- Records deleted more than 15 days ago, regardless of how they were deleted.
- A custom field’s data once the field is permanently erased. A deleted field sits recoverable for a period and then the data goes with it.
- Relationships that a restore does not rebuild. Undelete brings back the record and most links, but some lookups pointing at it are not restored.
Salesforce withdrew its last-resort paid data recovery service some years ago and now sells a backup product instead. Assume no one is coming to rescue you. If the data matters, you need your own backup running before the delete, and you need to have restored from it at least once.
A procedure that works at scale
- Define the set with a query, and save that query. Not a list view, a query.
- Extract the IDs and the full record data to a file first. That file is your backup for the run.
- Count children per parent object.
- Delete the lowest level first, in batches, so a failure leaves a consistent state.
Turn off the automation you do not need for the run, and record that you did. Delete triggers, flows and roll-up recalculations are frequently what makes a large delete take eleven hours instead of forty minutes.
Frequently asked
Does deleting free up storage immediately? No. Storage is released when the record leaves the recycle bin, not when it is deleted.
Can I undelete a whole cascade? Undeleting the parent restores the children that were cascade-deleted with it, provided they are still in the bin. Restoring a child on its own does not bring back its siblings.
Is Mass Delete in Setup safe? It is a small, slow tool with an option to bypass the recycle bin. Untick that option unless you specifically want a hard delete.
