Undoable Beats Confirm
Give dangerous actions one chance to regret, instead of asking three times in a dialog.
Rather than asking "are you sure" before the action, let it happen first and offer a window to undo.
What you'll run into:
- Users click "confirm" on every dialog without reading it
- Batch operations ask for confirmation on each item, until people give up using them
- When someone really deletes the wrong thing, the only recovery is coming to you
The problem with confirmation dialogs is that their cost distribution is inverted: out of a hundred actions, maybe one is a mistake — but all a hundred get interrupted. And once dialogs become routine, users form muscle memory and click "confirm" on reflex — the one genuine mistake still slips through. Undo moves the cost onto the one time something goes wrong: normal actions aren't interrupted at all, and the error case costs one second to click undo. Undo is one of the oldest and most stable interaction techniques in computer interfaces, present since the earliest editors. undo
Delete, send, and submit are high-frequency actions a user performs dozens of times a day; being interrupted for each one builds into real frustration, while genuine accidents are far rarer than you'd think. Undo only appears when something goes wrong and is otherwise invisible — which is exactly why it's friendlier than confirmation.
When you still need to confirm
Two questions decide it: is the action reversible, and how many people does the consequence affect? If both answers are "reversible, affects only me," use undo.
| Situation | Which one | Why |
|---|---|---|
| Delete a note, archive an email | Undo | Reversible, affects only yourself |
| Bulk delete, bulk status change | Undo | Confirming each item makes people stop using it |
| Send a message, submit a form | Undo | A few seconds of recall window is enough |
| Payment, transfer | Confirm | Money gone can't come back |
| Void a contract, publish publicly | Confirm | Affects others and is externally visible |
| Permanent delete, wipe data | Confirm | It's really gone. And raise the confirmation cost further |
When confirmation genuinely is needed, raise its cost so it can't be clicked through on reflex: require typing the contract number, turn the primary button into a danger color, replace "confirm" with a specific verb ("void the contract" instead of "confirm"). And consider the user's context: a confirmation dialog that pops up mid-way through focused batch work does the most damage.
How to implement undo
- Use soft delete at the data layer. Add a deleted flag instead of actually deleting. With it, undo is just flipping the flag back — almost zero cost.
- Put the undo action next to the result feedback. The toast after a delete should carry "Undo" right on it — the user shouldn't have to look elsewhere.
- Give a generous window. Five to ten seconds is common. Batch operations can be longer, or just turn it into a trash bin.
- After undo, the user should see the thing come back. Just toasting "Undone" isn't enough — that row in the list has to actually reappear.
- A trash bin is the long-term version of undo. When the short window isn't enough, the user still has a second way back.
This approach has a side benefit for vibecoding: soft delete plus undo essentially means data never really disappears. AI-generated code has a non-trivial chance of getting delete logic wrong; this safety net makes the cost of those errors much lower. The undo entry grows right on the result feedback, so it pairs naturally with Every Action Needs Feedback — build them together and the interaction loop is complete. One more detail: undo must undo all the way. If the record comes back but its attachment doesn't, the user believes everything is restored. Put "what the user sees after undo" into the acceptance criteria.
