Your churn number is higher than you want and you're not sure whether to fix onboarding, pricing or billing. Start with a two-quarter pull of every subscription that ended and tag each one as either a cancellation or a failed payment. That split decides your next month, and it's the first step of the diagnosis in SaaS Churn in 2026: Diagnose, Then Cure.
This post is the cure side. It covers the buildable fixes for each kind of churn, in the order I'd ship them, using the billing documentation that Stripe publishes and what the Callidus and BookBed case studies show. It supports the broader pillar on SaaS UX and growth.
How do you reduce SaaS churn when it's really two problems?
To reduce SaaS churn, separate voluntary churn (customers who decide to cancel) from involuntary churn (payments that fail), and fix the involuntary side first because those customers never chose to leave.
The size of the involuntary share depends on the dataset. Recurly's churn benchmarks, based on its network data from July 2026, report a median annual churn rate of 3.60% across industries, split into 2.34% voluntary and 1.25% involuntary. That puts roughly a third of churn in the failed-payment bucket in that dataset. For software businesses the same page reports a median annual churn rate of 3.04%, with top-quartile companies at 1.78% or below. Other benchmarks draw the line in different places, so treat these as a yardstick and measure your own split.
The two kinds need different owners. Voluntary churn is a product and positioning question. Involuntary churn is an engineering and email question, and it's usually the shorter project. If you need help reading your cohorts first, the diagnosis post walks through that, and SaaS billing and payments covers the plumbing that makes the numbers trustworthy.
How do you recover failed payments before they become churn?
Turn on automatic retries, send customers a failed-payment email that links to a page where they can update their card, and decide in advance what happens to the subscription after the last retry.
If you bill through Stripe, most of this is configuration. Stripe's retry documentation describes Smart Retries, which picks retry times from signals such as how many devices have presented a card recently. You choose the window: 1 week, 2 weeks, 3 weeks, 1 month or 2 months, with a recommended default of 8 tries within 2 weeks. You can also set a custom schedule of up to three retries. Stripe doesn't retry when there's no payment method, when the issuer returns a hard decline code, for India-issued cards, or when a Connect account has been disconnected. Those cases need a human-facing step: an email that gets the customer to a new card.
Stripe's customer email settings cover the rest of the loop. You can switch on failed-payment emails, expiring-card emails (sent one month before the card expires), trial-ending reminders (seven days before a trial ends) and renewal reminders, and each one links to a page where the customer can update their payment method. That page can be the Stripe-hosted Customer Portal or your own.
What happens after the final retry is your call. Stripe lets you pick one of three outcomes:
| After the last retry | Subscription status | What it means for you |
|---|---|---|
| Cancel the subscription | canceled | Clean end, customer has to resubscribe with new payment details |
| Mark as unpaid | unpaid | Invoices keep generating as drafts, no payment attempts, you revoke access |
| Leave past due | past_due | Invoices keep generating and charging per retry settings |
I'd pick unpaid or past_due over canceled while you're still learning your recovery rate, because the subscription, and the customer's history, stay intact if they fix the card later. That's a recommendation, and your billing model may point the other way.
What does the failure path look like in a real multi-tenant product?
Callidus, the React, Firebase and Stripe Connect clinic platform, shows what "handle the failure path" costs in code. According to its case study, it handles twenty Stripe webhook events end to end, including customer.subscription.trial_will_end and invoice.payment_action_required, which triggers a 3D Secure escalation and emails the clinic owner a hosted invoice URL. A scheduled function escalates tenants whose payments have failed. Trials run through a 3-day reminder, a 1-day reminder, expiry with a 3-day grace window and then suspension. During grace, pages stay viewable but writes are refused, enforced in both route gates and Firestore rules.
That combination is worth copying in spirit: a named state for "payment trouble", a visible deadline, and read-only access instead of a hard lockout. The integration mechanics are in setting up Stripe subscription billing for SaaS.
How do you stop customers from cancelling in the first place?
Get each new customer to one specific first result quickly, and trigger lifecycle emails from what they did or didn't do rather than from the calendar. Customers who never see the core value have little reason to stay.
Four moves cover most of it:
- Define one activation event. It's the moment a customer gets real value: the first booking created, the first invoice sent, the first report run. Track it as an event so you can see who reaches it.
- Cut the steps between signup and that event. Every setup screen before the first result is a place to leave. Defer configuration until after the customer has seen something work.
- Use empty states to teach. A blank dashboard should offer the next action and, where you can, sample data.
- Send behaviour-triggered nudges. "You created an account but haven't added your first unit" is more useful than a generic day-three email.
Once the event is tracked, compare the share of signups that reach it by acquisition channel and by plan. If one channel sends customers who rarely get there, that's a targeting problem, and no onboarding email will fix it. If every channel stalls at the same step, that step is the bug. This split is cheap to compute, and it tells you whether to spend the next week on product or on marketing.
Consider a booking product like BookBed, the Flutter, Firebase and Stripe platform whose main features include bidirectional iCal sync and an embeddable booking widget. This is a hypothetical, not a measured result: a host who signs up but never connects a calendar hasn't touched the feature that makes the product useful, so "calendar connected" is a sensible candidate for the activation event, and the nudge for anyone who stalls before it writes itself. BookBed's billing is wired through Stripe but isn't activated for paid traffic, so I'm describing the design logic here, not retention data.
For a step-by-step treatment of the first session, see the B2B SaaS onboarding flow that activates.
How should a cancellation flow work?
A cancellation flow should ask one question, offer an option that fits the answer, and still let the customer leave in a couple of clicks. Its job is to collect the reason and offer a real alternative, not to block the exit.
Stripe's customer portal configuration gives you the building blocks. Cancellation is on by default, cancellation reasons are captured by default, and retention coupons, which let you offer a coupon before a customer cancels, are off until you enable them. The reasons you collect are the raw material for the diagnosis in the other post, so switch them on before you design anything fancier.
Then decide what "pause" means, because Stripe has two versions and they behave differently:
| Pause payment collection | Pause subscription | |
|---|---|---|
| Customer keeps access | Yes | No, service delivery stops |
| Invoices | Keep generating, payment isn't collected | Generation stops until resume |
| Status | Stays active | Becomes paused |
| Set with | pause_collection on the subscription | The pause endpoint |
| Notable limits | You choose how invoices are handled: draft, uncollectible or void | Needs flexible billing mode and API version 2025-06-30.preview or later, and customers can't pause themselves in the portal |
Both are described in Stripe's docs on pausing payment collection and pausing subscriptions. Pausing collection works as a grace period, because the customer keeps the service for free while they sort out money. Pausing the subscription suits a customer heading into a quiet season. The pause endpoint is a preview API at the time of writing, so check the current version before you build on it.
Match the offer to the reason. A price complaint can justify a coupon or a smaller plan. A missing feature deserves an honest answer about your roadmap. A customer who left because the product didn't work won't be kept by a discount, and the save offer just delays the same cancellation.
What order should you do all this in?
If you're a solo founder with limited time, this is the order I'd work in:
- Tag every cancellation with a reason and build cohort curves, so you can see where churn comes from.
- Switch on retries and the failed-payment, expiring-card and renewal emails.
- Define the activation event and cut the steps before it.
- Add a pause option and a one-question exit survey.
Pricing changes aren't on the list because the data from steps one to four should tell you whether price is the problem. If you want a second opinion on your own numbers, get in touch.
Which of your last twenty ended subscriptions were failed payments rather than decisions? Count them before you touch your pricing page.
