Cancel flow best practices: examples without dark patterns
How to design a SaaS cancel flow that saves customers honestly: a short reasons list, one offer per reason, a visible cancel button, copy examples and metrics.
A cancel flow is the short sequence a customer sees between clicking “Cancel subscription” and the subscription actually ending. Done well, it answers one question (“why are you leaving?”) and makes one relevant offer. Done badly, it becomes a maze of guilt-trip screens, hidden buttons and phone-only cancellation, which annoys customers and, increasingly, regulators.
This guide covers how to build the first kind: what to ask, what to offer, how to write the copy, and how to measure whether it works.
The principle: one question, one offer, always an exit
A good cancel flow has three steps at most:
- Reason. Ask why the customer is leaving, with a short list of options.
- Offer. Show one offer that matches that reason, or none if nothing fits.
- Confirm. Confirm the cancellation and state exactly what happens next (end date, data retention, how to come back).
On every step, a “Cancel now” button stays visible and works in one click. The customer should never have to accept or decline an offer to reach the exit.
This is not only good manners. California’s updated automatic renewal law, in force since July 1, 2025, allows a business to present a save offer to consumers who cancel online only if it also shows a clear, continuously displayed way to cancel (Davis Wright Tremaine summary of AB 2863). The FTC has also named obstructive cancellation as a dark pattern in its 2022 staff report Bringing Dark Patterns to Light. See our click-to-cancel rules overview for the legal detail.
Step 1: the reasons list
The reasons list does two jobs: it routes the customer to the right offer, and it gives you data. Both get worse when the list is long.
Keep it to five to seven options
Pick reasons you can act on. A typical B2B SaaS list:
| Reason (customer-facing) | Internal code | What you can do about it |
|---|---|---|
| It’s too expensive | price |
Discount, downgrade |
| I’m not using it enough | low_usage |
Pause, onboarding help |
| It’s missing a feature I need | missing_feature |
Roadmap info, call |
| I switched to another tool | competitor |
Ask which one, call |
| It was too hard to set up or use | too_complex |
Setup call |
| My project or company ended | no_need |
Pause, or no offer |
| Something else | other |
Free text, no offer |
Rules for the list
- Use the customer’s words, not yours. “I’m not using it enough” beats “Low engagement.”
- One choice, not checkboxes. You need one primary reason to pick one offer. Add an optional free-text field for detail.
- Make the question skippable. If the customer wants out, “Skip and cancel” should work.
- Shuffle the order (except “Other”) if you want cleaner data; the first option gets picked more often by people in a hurry.
- Keep internal codes stable. If you rename a reason later, keep the code so your historical data stays comparable.
Step 2: one offer per reason
The worst cancel flows show every offer to everyone: a discount, then a pause, then a downgrade, then a “talk to us” screen. The customer has to decline four times. Instead, map each reason to at most one offer.
| Reason | Offer that fits | Why |
|---|---|---|
| Too expensive | Downgrade to a cheaper plan, or a time-limited discount | Addresses cost directly |
| Not using it enough | Pause for one to three months | The need may come back; a discount on something unused does not help |
| Missing a feature | A short call, or a link to the roadmap item | You might solve it, or at least learn |
| Switched to a competitor | A call, or no offer | Discounts rarely win back someone who has already migrated |
| Too hard to use | A setup call | The problem is effort, not price |
| No longer needed | No offer | Respect it; make coming back easy |
Two things are worth noticing. First, “no offer” is a valid answer: pushing a discount on someone whose company shut down wastes their time and your margin. Second, a discount is the right answer less often than people assume. Our guide to pause vs discount vs downgrade goes deeper on when each one fits.
Offer guardrails
- Limit repeat offers. A customer who took a discount last quarter should not see the same discount again. Otherwise you train customers to start cancelling to get a lower price.
- Make the terms explicit. “50% off for your next 3 months, then back to $49/month” is honest. “Special price!” is not.
- Make acceptance instant. If the customer clicks “Accept,” apply the coupon, pause or plan change right away and show confirmation. No “our team will be in touch.”
Step 3: confirmation
The confirmation screen is part of the flow, not an afterthought. It should state:
- The exact date access ends (often the end of the paid period).
- What happens to their data, and for how long it is kept.
- That no further charges will be made.
- How to restart, in one line.
Send the same information by email. A customer who is unsure whether cancellation went through is a customer who files a chargeback.
Copy examples
Good cancel copy is short, specific and neutral. Here are original examples for each screen.
Reason screen
Before you go, what’s the main reason? Your answer helps us improve. You can skip this and cancel right away.
[Cancel now]
Offer screen (reason: too expensive)
Would a smaller plan work? The Basic plan is $19/month and keeps your projects and history. You’d lose team seats beyond 3.
[Switch to Basic] [No thanks, cancel now]
Offer screen (reason: not using it enough)
Want to pause instead? We’ll stop billing for up to 3 months and keep everything as it is. You can resume any time, and we’ll remind you a week before billing restarts.
[Pause for 1 month] [Pause for 3 months] [Cancel now]
Offer screen (reason: missing a feature)
Which feature were you missing? If it’s on our roadmap, we’ll tell you where it stands. If you’d rather talk it through, book 15 minutes with the product team.
[Book a call] [Cancel now]
Confirmation screen
Your subscription is cancelled. You have access until December 14, 2026. You won’t be charged again. We keep your data for 90 days, then delete it. To restart, sign in and choose a plan.
Copy to avoid
| Pattern | Example | Why it’s a problem |
|---|---|---|
| Confirmshaming | “No thanks, I don’t care about growing my business” | Guilt instead of information |
| Hidden exit | A grey “cancel” link below the fold | Obstruction; risky under state law |
| Fake urgency | “This offer expires in 2:00 minutes” | Manipulative, usually untrue |
| Forced contact | “Call us to cancel” when signup was online | Restricted by California for online signups |
| Endless loop | Offer after offer after offer | Wears people down instead of helping |
| Ambiguous buttons | “Continue” (to what?) | Customer can’t tell which button cancels |
Design checklist
Use this before shipping a cancel flow:
- “Cancel now” is visible and works in one click on every screen.
- Three screens or fewer from “Cancel” to confirmation.
- Reason question is optional.
- At most one offer, and it matches the reason.
- Offer terms (amount, duration, what happens after) are stated in full.
- Accepting the offer applies it immediately.
- Customers who already used an offer recently don’t see it again.
- Confirmation shows end date, data retention and no further charges.
- Confirmation email is sent.
- Flow works with keyboard only and with a screen reader.
- Flow is available wherever signup was (web, iOS, Android, desktop).
- Legal review done for your markets (US states, EU, UK).
Measuring a cancel flow
A cancel flow is only worth keeping if it changes outcomes without creating new problems. Track these per reason, not just overall.
| Metric | Definition | What to watch for |
|---|---|---|
| Flow starts | Customers who clicked “Cancel” | Baseline volume |
| Offer acceptance rate | Accepted offers / flows that showed an offer | Low rate means the offer doesn’t fit the reason |
| Save rate | Customers still subscribed N days after accepting / flow starts | Use 30, 60 and 90 days, not just “accepted” |
| Saved revenue | MRR still active N days after a save | Subtract the discount cost |
| Re-cancel rate | Saved customers who cancel later | High rate means you’re delaying churn, not preventing it |
| Complaints and chargebacks | Support tickets and disputes about cancellation | Should not go up |
A few measurement rules:
- Count a save only if it lasts. A customer who accepts a discount and cancels a month later was not saved. Stripe’s own retention reporting, for example, counts a save only if the customer stays subscribed for at least 7 days after accepting an offer (Stripe docs); for SaaS, a longer window is more telling.
- Price in the offer. A 50% discount for three months on a $100/month plan costs $150. If the customer stays for only four months, the save was worth $250 in revenue, not $400.
- Keep a holdout. Show a small random group the flow without the offer (reason question and confirmation only). Comparing the two groups is the only way to know how many saves the offer actually caused, since some of those customers would have stayed anyway.
- Read the free text. The “Other” answers are where you find reasons you didn’t list.
Where to build it
You have three options. Stripe’s customer portal includes a basic cancellation page with a fixed reasons list and a retention coupon, and it is enough for many early-stage products (our comparison). You can build the flow yourself, which gives full control but means maintaining offers, eligibility rules and analytics. Or you can use a dedicated tool.
How NoChurn helps
NoChurn’s cancel flows follow the structure in this guide: reason, then one matching offer (a discount through a Stripe coupon, a pause, a downgrade or a call), then confirmation. A one-click “Cancel now” button is visible on every step. You can use the hosted modal (themes, colors, fonts, borders, logo, custom CSS and a visual editor) or the headless API to build the flow in your own design on web, desktop, iOS and Android. Cancel reasons feed the win-back emails sent at 30, 60 and 90 days. Every feature is on every plan, and the price depends only on your MRR (pricing).