How do I immediately prorate subscription upgrades?

Normally when a customer upgrades their subscription Stripe will tack on a proration amount to their next invoice. They'll be able to use the upgraded service without actually paying for it. What if you want to prorate the customer's subscription right away? That is, you don't want to wait until the next billing cycle to start, you want to collect the proration amount from them immediately.

With Stripe's new ability to preview subscription updates this becomes pretty easy. First, get the preview amount like in the previous post:

upcoming = Stripe::Invoice.upcoming(
    customer: customer_id, 
    subscription: subscription_id,
    subscription_plan: 'monthly_25'

proration_amount = upcoming.lines.last.amount

Now that you have the amount, you can easily create a new invoice, immediately pay it, and upgrade the customer without proration:

customer = Stripe::Customer.retrieve(customer_id)
sub = customer.subscriptions.retrieve(subscription_id)

item = Stripe::InvoiceItem.create(
  customer: customer_id,
  subscription: subscription_id,
  amount: proration_amount

invoice = Stripe::Invoice.create(
  customer: customer_id,
  subscription: subscription_id

invoice =

if invoice.paid
  sub.plan = 'monthly_25'
  sub.prorate = false
  invoice.closed = true

The logic around the paid attribute above is important, because if the payment fails for some reason you don't want to upgrade the subscription, and you also don't want that invoice to retry automatically. This logic ensures that a customer who's payment fails won't get extra free services while Stripe's automatic retries are happening.

Mastering Modern Payments

Build a Better Payment System

Get a free five part email course all about Stripe and Rails, including the first three chapters of Mastering Modern Payments.

No spam. Unsubscribe at any time.
Pete Keen Portrait Pete Keen has been professional software developer for a decade, building payment systems and other software for companies large and small. He blogs here and at