Back

How to Handle SaaS Upgrades/Downgrades in Stripe Without Breaking Access

MT
MVPHub Team
4 min read

How to Handle SaaS Upgrades/Downgrades in Stripe Without Breaking Access

Plan changes are one of the trickiest parts of SaaS billing. Upgrade too eagerly and you overcharge. Downgrade poorly and users keep premium features for free. Here's how to handle both correctly with Stripe.


Upgrade: Give Access Immediately

When a user upgrades (Starter → Pro), they should get premium features right away.

Implementation

Use stripe.subscriptions.update() with the new price ID. Stripe handles proration automatically — the user gets a credit for unused time on the old plan and is charged the difference for the new plan.

Proration Options

OptionBehaviorBest For
create_prorations (default)Charge difference immediatelyStandard upgrades
noneNo proration, new price starts next periodSimplicity
always_invoiceGenerate and charge a proration invoice immediatelyWhen you need immediate payment

Access Control

  1. Update subscription in Stripe
  2. Webhook customer.subscription.updated fires
  3. Update user's plan in your database
  4. User immediately has access to new plan features

Downgrade: Keep Access Until Period End

When a user downgrades (Pro → Starter), they should keep their current plan until the end of the billing period.

Implementation

Use stripe.subscriptions.update() with the new price ID and proration_behavior: 'none'. Schedule the change for the end of the current period using billing_cycle_anchor: 'unchanged'.

Alternatively, update the subscription's items with proration_behavior: 'none' — the new price takes effect at the next invoice.

Access Control

  1. Schedule downgrade in Stripe
  2. Store the pending plan change in your database
  3. User keeps current (higher) plan features until period ends
  4. Webhook fires at period end with the new plan
  5. Update user's access in your database

Edge Cases to Handle

User Upgrades Then Downgrades in Same Period

Scenario: User is on Starter, upgrades to Pro on day 5, then wants to downgrade back to Starter on day 10.

Solution: Process the downgrade normally — schedule it for end of period. The user keeps Pro access until then. The proration from the upgrade still applies.

User on Trial Wants to Change Plans

Scenario: User is on a Pro trial but wants to switch to Business before the trial ends.

Solution: Update the subscription's price. The trial continues on the new plan with the same end date.

User Cancels Then Wants to Resubscribe

Scenario: User canceled (set to expire end of period), but changes their mind.

Solution: Use stripe.subscriptions.update() with cancel_at_period_end: false to remove the scheduled cancellation.


Database Schema for Plan Changes

FieldPurpose
currentPlanThe plan the user currently has access to
scheduledPlanThe plan they'll switch to at period end (if downgrading)
currentPeriodEndWhen the current billing period ends
cancelAtPeriodEndWhether the subscription is set to cancel

Golden rule: Always check currentPlan for access control, not scheduledPlan. The user should have access based on what they're currently paying for.


Testing Plan Changes

Test CaseExpected Result
Upgrade Starter → ProImmediate access to Pro features, prorated charge
Downgrade Pro → StarterKeep Pro access until period end, then switch
Cancel subscriptionKeep access until period end, then revoke
Reactivate after cancelAccess restored, cancel flag removed
Upgrade during trialTrial continues on new plan
Multiple changes in one periodLatest change takes effect, proration is correct

Building billing? Read How to Build SaaS Billing With Stripe.

Need multi-tier plans? See Building Multi-Tier SaaS Plans.


Working products with full source code — live demo, one-time purchase, instant delivery.

Browse the marketplace
GR LIVEecommerce

Groover Multi-Purpose Store

$149

A fully-polished, multi-purpose e-commerce template engineered for brands that need the full feature set on day one — not a minimal starter you outgrow in a month. Groover ships with a live Medusa-backed catalog, category + collection merchandising, search with multi-facet filtering (category, collection, price, sale, stock, sort), product-detail with variant selection + image gallery + stock messaging + related products, Stripe Elements checkout with provider-aware setup panels, account dashboard with guest order lookup and authenticated order history, customer auth with login/register/logout/profile edit, wishlist with guest browser persistence and signed-in customer sync, blog list + detail, store directory, track-order page, branded 404, About/Contact/FAQ/Terms legal shell, GTM-friendly dataLayer wired into PDP/cards/wishlist/cart/checkout/search, locale + RTL foundation with persistent language switcher, PWA installability baseline, theme switching that applies before hydration and persists in both local storage and cookies, header active-route navigation with live mini-cart summary, skip-link / focus accessibility basics, app-level and route-level loading fallbacks, a recoverable error boundary, generated robots.txt and sitemap.xml, shared SEO metadata helpers, and a Playwright / Vitest / Lighthouse test harness. Every copy string lives in a typed content map so rebranding is a find-and-replace pass, not a code rewrite. Deploy it as-is or use it as the most complete starting point you can buy for a serious storefront.

★★★★★0 soldAstro · Medusa
FU LIVEecommerce

Furniture Store

$49

An elegant furniture and home furnishing e-commerce app with a design-forward Next.js storefront for SEO-optimized product pages and server-rendered category browsing. Alternative framework and mobile ports are available on demand. The visual design emphasizes large product imagery, room-based browsing, and material/color variant selection. Built with Radix UI, shadcn/ui, Tailwind CSS, and Framer Motion for a premium feel. Connects to any headless commerce backend — Medusa JS SDK integration is included. Form handling via React Hook Form with Zod validation ensures robust checkout and account flows. Great for furniture brands, interior design shops, or home decor marketplaces.

★★★★★0 soldExpo · Next.js
PE LIVEecommerce

Perfume Store

$49

A luxury-styled perfume and fragrance e-commerce app built for premium brand presentation. The ready-to-buy Next.js storefront features rich product pages with scent profiles, bottle size variants, gift set options, and server-rendered collections. Mobile, backend, and alternative framework ports are available on demand. The design uses shadcn/ui and Tailwind CSS with an elegant, minimalist aesthetic suited for luxury goods. Easy to customize — swap product data, update branding, and deploy. Perfect for perfume brands, fragrance boutiques, or niche scent marketplaces.

★★★★★0 soldMedusa · Expo

Keep reading — popular SaaS guides on MVPHub.

All SaaS articles

Explore other MVP verticals

MVPHub publishes templates and guides for ecommerce, SaaS, marketplaces, AI apps, booking platforms, subscription stores, directory sites, and more. Here are fresh picks from other verticals.