Stripe subscription proration explained — change plans without wiping data

Proration is how Stripe charges or credits the difference when a customer upgrades or downgrades mid-cycle. The danger isn't the math — it's the cancel-and-recreate antipattern that silently destroys billing history, trial state, and your retention analytics. Here's the right way.

The antipattern that breaks everything

Don't do this
// ❌ Cancel old, create new — wipes history, breaks cohort analytics
await stripe.subscriptions.cancel(oldSubId);
await stripe.subscriptions.create({ customer, items: [{ price: newPriceId }] });

This fires subscription.deleted + subscription.created, so your analytics see a churn + a new signup for what was actually an upgrade. It can re-grant trials, drop the payment method, and lose coupon state. Your MRR retention curve becomes fiction.

The right way: modify in place

Do this
const sub = await stripe.subscriptions.retrieve(subId);
const updated = await stripe.subscriptions.update(subId, {
  items: [{ id: sub.items.data[0].id, price: newPriceId }],
  proration_behavior: "create_prorations",
});

Same subscription.id, history intact, proration handled, no fake churn event.

proration_behavior — the 3 options

ValueWhat happensUse when
create_prorationsAdds proration line items to the NEXT invoice (default)Standard upgrades; charge difference at next cycle
always_invoiceCreates prorations AND invoices immediately (charges card now)Upgrades where you want the money now
noneNo proration; old price runs out the current period, new price next cycleDowngrades you don't want to credit; simple plan swaps

The upgrade-vs-downgrade nuance

When to use Subscription Schedules instead

If your plan logic has phases (trial → monthly → annual, or scheduled future downgrades), Subscription Schedules wrap a subscription with explicit time-based phases — cleaner than mutating mid-cycle and reasoning about proration each time. Overkill for 2-3 simple tiers; worth it for complex phase logic.

Worried your plan-change code has the antipattern?

I audit Stripe subscription plan-change logic for the cancel-recreate bug, proration misconfigurations, and trial-gaming exposure — then deliver the fix for your stack. $199 one-time, full refund if I don't find ≥3 issues.

See the audits →

Related tools & guides