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 list

Step 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?

MethodSetup timeCostBest for
Build yourself20-40 hoursFree (your time)Full control, custom UX
Stripe Portal30 minFreeQuick start, basic needs
Widget (SaveMRR)3 min$19/moBest 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.

Your Stripe has a leak. Let's find it.

Free Revenue Autopsy — paste your Stripe key, see every dollar you lost in 60 seconds. No card needed.

Run my free autopsy