Getting users to subscribe is the easy part. Managing every possible subscription state change — upgrade, downgrade, pause, reactivation, cancellation — is where most SaaS developers get stuck. Here's a complete implementation guide.
Plan Upgrades
When a monthly Starter subscriber upgrades to Pro: Stripe prorates the charge. If they're 15 days into their monthly cycle, they get credit for the remaining 15 days on Starter and are charged the prorated Pro price immediately.
Implementation: stripe.subscriptions.update(subscriptionId, { items: [{ id: itemId, price: newPriceId }], proration_behavior: 'create_prorations' }). The user gets immediate access to Pro features — don't wait for a webhook to activate access on upgrades.
Plan Downgrades
Downgrades should take effect at the end of the current billing period — not immediately. This prevents: partial-period refund complexity, users gaming the system (upgrading on day 1, downgrading on day 28 to use Pro features for $0.10).
Implementation: proration_behavior: 'none' with trial_end: 'now' or scheduling the price change for the next period via Stripe's subscription schedules.
Cancellation Flow
Cancellation with friction that isn't annoying:
- Show a "Before you go" modal with a pause option (if you offer it)
- Show a one-question exit survey ("Why are you cancelling?")
- Optionally offer a discount or pause ("What if we gave you 50% off for 2 more months?")
- Confirm cancellation — access continues until end of billing period
- Send a cancellation confirmation email with a reactivation CTA
Subscription Pause
Offering a "pause" option (suspend billing for 1–3 months without cancelling) reduces cancellations by 15–25%. Stripe supports subscription pauses natively. Paused subscriptions resume automatically at the end of the pause period.
Build Complete Subscription Management
I take 2 clients per month. Ship your SaaS in 2–4 weeks with a developer who has done it 350+ times.
Start on Fiverr →Failed Payment Dunning
When a renewal payment fails, Stripe retries automatically (1, 3, 7 days by default). Configure Stripe's Smart Retries for better success rates. Your webhook listener should: notify the user immediately on first failure, restrict access after the third failure, and send escalating urgency emails during the dunning window.
Implementing Dunning for Failed Payments
Failed payments are one of the largest sources of involuntary churn in SaaS. Stripe's Smart Retries automatically re-attempts failed charges at optimal times using machine learning, but you also need a dunning email sequence — a series of emails that notify customers of payment failure and prompt them to update their card. A typical sequence: immediate notification on failure, reminder at day 3, final warning at day 7 with account suspension notice, account suspension at day 10. Recovering 30–50% of failed payments through dunning is a realistic target with a well-implemented sequence.