Forgiveness through confirmation and prevention
When an action can't be made reversible, the next-best forgiveness is requiring deliberate intent. The user must take an explicit, considered step before the irreversible thing happens. The challenge: confirmation overuse trains users to dismiss it on autopilot, defeating the purpose. Confirmation must be reserved for the moments when it earns its friction.
When confirmation is appropriate
A useful test before adding confirmation: is the action irreversible and high-stakes?
- Irreversible + high-stakes → confirm. (Account deletion, ownership transfer, large financial transaction.)
- Reversible + high-stakes → use undo / soft-delete instead. Confirmation here is fatigue-inducing.
- Irreversible + low-stakes → consider whether it should be reversible. If it must be irreversible, a light confirmation may suffice.
- Reversible + low-stakes → no confirmation. Just do it; let undo catch mistakes.
Confirmation strength
Match confirmation friction to action severity:
Light confirmation: "Yes / No" dialog
Cancel reservation?
[ Cancel ] [ Cancel reservation ]
For actions the user clearly initiated, where the dialog mostly catches accidental clicks. The user reads the title, picks an option.
Medium confirmation: dialog with summary
Delete project "Acme Q4"?
This deletes 24 tasks and 8 attached files.
[ Cancel ] [ Delete project ]
For actions where the user benefits from seeing what they're about to lose. The summary gives them a chance to step back.
Strong confirmation: type-to-confirm
Delete project "Acme Q4"?
This deletes 24 tasks and 8 attached files. Cannot be undone.
To confirm, type the project name below:
[ Acme Q4__________ ]
[ Cancel ] [ Delete project ] (button enabled only when name matches)
For irreversible high-stakes actions. The user must actively type the resource name, breaking autopilot. The button stays disabled until the confirmation matches.
Strongest: re-authentication
This action requires re-authentication.
Enter your password to continue.
[ Password__________ ]
[ Cancel ] [ Continue ]
For account-affecting actions: deleting account, changing email, transferring ownership, viewing audit logs. Re-authentication catches both autopilot mistakes and someone-else-using-my-session attacks.
Type-to-confirm: the canonical pattern for irreversible action
<dialog id="delete-dialog">
<h2>Delete workspace "Acme Inc"?</h2>
<p>
This permanently deletes the workspace, all 47 projects, all 12 members'
access, and 3.2 GB of files. This cannot be undone.
</p>
<p>To confirm, type the workspace name below:</p>
<input id="confirm" placeholder="Acme Inc" autocomplete="off" />
<div class="actions">
<button onclick="closeDialog()">Cancel</button>
<button id="confirm-btn" disabled class="destructive">
Delete workspace permanently
</button>
</div>
</dialog>
<script>
const input = document.getElementById('confirm');
const btn = document.getElementById('confirm-btn');
input.addEventListener('input', () => {
btn.disabled = input.value !== workspace.name;
});
</script>
What this achieves:
- The dialog must be opened deliberately.
- The consequences are stated plainly.
- The user must type — an active gesture that breaks autopilot.
- The button is disabled until the typed name matches, so even autopilot Enter doesn't trigger.
For actions that should genuinely never happen by accident, this stack is appropriate.
Re-authentication for security-sensitive operations
<button onclick="requireReauthThen('delete-account')">
Delete account
</button>
<dialog id="reauth-dialog">
<h2>Confirm your identity</h2>
<p>For your security, please re-enter your password to continue.</p>
<input type="password" id="reauth-password" autofocus />
<div class="actions">
<button onclick="closeDialog()">Cancel</button>
<button id="reauth-submit">Continue</button>
</div>
</dialog>
Use re-authentication when:
- The action affects security or billing.
- The action affects other users' access.
- The action would be devastating if performed by someone with stolen session access.
- Compliance requires it.
The cost: an extra password entry. The benefit: a second opportunity for the user to reconsider, plus protection against session theft.
Structural prevention (the highest forgiveness)
Stronger than any confirmation: making the wrong action impossible.
Disable the action when invalid
A "Submit" button disabled when the form has errors. The user can't trigger the failure path. (Pair with inline error explanations so the user knows what's missing — see affordance-false-and-anti.)
Type-restricted inputs
<input type="email"> rejects non-email format. <input type="number"> rejects non-numeric. <input type="tel"> shows a numeric keyboard on mobile. Each is structural prevention of certain input errors.
Constraint by selection rather than typing
A <select> for state names prevents typos that a free-text field would allow. A date picker prevents impossible dates. A typeahead constrained to known values prevents misspelled selections.
Physical / hardware analogies
The USB-C connector that can't be inserted upside-down. The pill organizer that shows visual state. The medical injector that can't deliver a dangerous dose.
Required-field marking + blocked submit
<form>
<label>Email <span class="required">*</span>
<input type="email" required />
</label>
<button>Submit</button>
</form>
The browser blocks submission with focus on the missing field. Native scaffolding for prevention.
Anti-patterns
- Confirmation fatigue. "Are you sure you want to save? / open? / apply?" Every routine action confirmed. Users dismiss everything on autopilot.
- Pre-selected destructive option. A confirm dialog with the destructive button as default Enter target. Users who hit Enter without reading commit the destruction.
- Trivial type-to-confirm. Forcing users to type "DELETE" for a routine archive operation. Heavy friction for low-stakes action.
- Hidden cancellation path. A confirm dialog with no Esc, no backdrop dismiss, just two buttons. The user feels trapped.
- Confirmation as the only forgiveness. Apps where every destructive action is confirmed but nothing is reversible. Confirmation alone is insufficient — users still make mistakes.
- Sneaky double-negatives. "Are you sure you don't want to keep your account?" Users misread; mistakes happen.
Calibrating friction to stakes
A useful framing: every confirmation step is a tax. Ask whether the tax is worth it for this specific action.
| Action | Reversibility | Stakes | Recommended confirmation |
|---|---|---|---|
| Save | Reversible | Low | None |
| Apply filter | Reversible | Low | None |
| Archive item | Reversible (toast undo) | Low | None |
| Delete (soft) | Recoverable in trash | Medium | None |
| Empty trash | Irreversible | Medium | Light dialog |
| Delete project | Irreversible | High | Strong dialog with summary |
| Delete account | Irreversible | Very high | Type-to-confirm + reauth |
| Transfer ownership | Irreversible | Very high | Type-to-confirm + reauth + email verification |
Each step up the friction ladder should correspond to a step up in stakes.
Heuristics
- The reversibility-first check. Before adding any confirmation, ask: can this be made reversible instead? If yes, do that.
- The autopilot test. If a typical user would dismiss the confirmation without reading, the confirmation isn't doing its job. Either remove it or make it harder to dismiss without reading.
- The "what would they regret?" test. For irreversible actions, imagine the user a week later realizing they made a mistake. Did the confirmation do enough to prevent that?
- The disabled-button question. When you reach for confirmation, ask whether structural prevention (disabling the action when it shouldn't apply) would work better.
Related sub-skills
forgiveness(parent).forgiveness-undo-and-soft-delete— the preferred alternative when reversibility is possible.affordance-false-and-anti— disabled states and structural prevention.constraint— input constraints prevent invalid actions.expectation-effect— confirmation buttons in unexpected positions surprise users.accessibility-understandable(process) — confirmation flows must be operable for all users.