How to Add a Cancel Flow to Your Stripe SaaS
Most SaaS apps handle cancellation in one of two ways: a "cancel" button that fires a Stripe API call and immediately ends the subscription, or a redirect to Stripe's Customer Portal. Both work. Both leave money on the table. A proper cancel flow adds an exit survey and a retention offer between "I want to cancel" and "you're cancelled." Here are three ways to add one.
Method 1: Build it yourself
If you want full control, you can build a cancel flow from scratch. Here's the architecture:
Step 1: Replace immediate cancellation with a modal
Instead of calling stripe.subscriptions.cancel() when the user clicks "Cancel," show a modal component:
// React example
const [showCancelFlow, setShowCancelFlow] = useState(false);
// Instead of direct cancel:
<button onClick={() => setShowCancelFlow(true)}>
Cancel Subscription
</button>
{showCancelFlow && (
<CancelFlowModal
onClose={() => setShowCancelFlow(false)}
onConfirmCancel={handleCancel}
onAcceptOffer={handleAcceptOffer}
/>
)}Step 2: Build the exit survey
The modal should have two screens. Screen 1 is the exit survey:
const cancelReasons = [
{ id: "too-expensive", label: "Too expensive" },
{ id: "not-using", label: "Not using it enough" },
{ id: "missing-features", label: "Missing features I need" },
{ id: "switched", label: "Switched to another tool" },
{ id: "other", label: "Other reason" },
];
// Render as clickable buttons, not a dropdown
// Users are more likely to respond when it's
// a single click vs selecting from a listStep 3: Show a retention offer based on the reason
Screen 2 shows an offer tailored to their reason:
- "Too expensive" → Create a Stripe coupon and apply it:
stripe.subscriptions.update(subId, { coupon: couponId }) - "Not using it enough" → Pause the subscription:
stripe.subscriptions.update(subId, { pause_collection: { behavior: 'void' } }) - "Missing features" → Link to your roadmap or offer a founder call
- "Switched to competitor" → Aggressive discount or extended trial of premium features
Step 4: Handle the response
If they accept the offer, apply the coupon/pause in Stripe and close the modal. If they decline, proceed with the cancellation. Log everything — the reason, the offer shown, and whether they accepted.
Time to build: 20-40 hours depending on your stack. Plus ongoing maintenance for Stripe API changes, new offer types, and analytics.
Method 2: Use Stripe's Customer Portal
Stripe's Customer Portal has a built-in cancellation flow. You can configure it in Dashboard → Settings → Customer portal.
What you get:
- A cancellation reason selector (you choose the options)
- Optional retention offers (coupon-based)
- Stripe-hosted — no code to maintain
What you don't get:
- Custom UI — it's Stripe's design, not yours
- Smart offers based on reason — it's the same offer for everyone
- Analytics — you get the cancel reason in the webhook, but no dashboard, no save rate tracking
- Pause option — Stripe Portal doesn't support subscription pausing in the cancel flow
Time to setup: 30 minutes. It's a reasonable starting point if you have zero cancel flow today.
Method 3: Drop in a cancel flow widget (fastest)
Cancel flow widgets like SaveMRR's Cancel Shield give you a full-featured cancel flow with one line of JavaScript:
<script src="https://cdn.savemrr.co/widget.js"
data-api-key="smrr_your_api_key"
data-trigger="#cancel-button">
</script>What you get:
- Exit survey with 5 reason buttons
- Personalized offers by reason (Growth plan) or static offers (Starter)
- Automatic Stripe actions — applies coupons, pauses subscriptions, no backend work
- Light/dark mode auto-detection
- White-label branding (Growth plan)
- Analytics dashboard — save rate, cancel reasons, offer acceptance
- Under 5KB gzipped — won't slow down your app
Time to setup: 3 minutes. Paste the script tag, point it at your cancel button. If you remove the script, your cancel flow goes back to what it was. Zero risk.
Which method should you choose?
| Method | Setup time | Cost | Best for |
|---|---|---|---|
| Build yourself | 20-40 hours | Free (your time) | Full control, custom UX |
| Stripe Portal | 30 min | Free | Quick start, basic needs |
| Widget (SaveMRR) | 3 min | $19/mo | Best ROI, smart offers, analytics |
My honest recommendation: if you have no cancel flow today, start with Method 3 (SaveMRR Cancel Shield). It takes 3 minutes, costs $19/mo, and starts saving customers immediately. You'll collect exit survey data from day one. If you outgrow it and want full custom control, you'll have months of data on what offers work and what reasons dominate — which makes building your own flow much easier.
And remember: Cancel Shield is just one of SaveMRR's 5 engines. The same $19/mo also gets you Revenue Rescue (payment recovery), Churn Radar (pre-cancel detection), and a free Revenue Autopsy that shows exactly what you're losing right now.