The Case for Soft Deletes

I always liked soft deletes as a feature because it allowed customers to undo their potential mistakes. It also allowed the engineers to better debug, so it was just an overall nice feature, right? It was also a comforting sort of safety net, because the alternative is that if someone deletes something, you might have to roll back the database, you might have to go digging in the logs, et cetera. It also doubles as a rough audit log, since the deleted rows are still in the table, just tombstoned.

But now that increasingly agents are used to access our systems, I do think soft deletes have a much bigger use case. If your agent goes rogue and starts deleting a bunch of stuff, the agent is much faster than a human could delete it. Even a human could use a script, but the agent can do it without a human really knowing. A human has to actively run the script. The agent could just do it in the background.

If you build an application with soft deletes in mind and gate it by an API, that gives your AI an additional guardrail. To me, that’s a basic rule of letting agents touch production. The API protects itself from bad inputs, sort of the same way validation does. The agent can ask for whatever it wants, but a delete is still just a reversible delete.

And honestly, that’s the part I like most about it. If the agent does go off the rails and deletes everything it can reach, you haven’t really lost anything. It’s all still there with a flag on it, so recovering is just a matter of flipping those flags back. Worst case, the app is down for a little while, but the data is never actually gone.

Soft deletes aren’t free, though. You have to remember to filter out the deleted rows on basically every query, and the day you forget is the day you show someone data they thought was gone. Unique constraints get awkward too, since a deleted row still occupies that email or that slug. And the whole thing only holds if everything goes through the API. The moment someone runs a script straight against the database, the safety net isn’t there.

As always, there is, of course, a use case for hard deletes. If you provision infrastructure, it’s probably a good idea to deprovision that part so you don’t incur cost when something’s deleted. Even that you could delay by a certain time window, but it’s really up to the app. Generally, when I can, I will do soft deletes, just for the convenience, the laziness, but now more and more also as the additional safeguard.