Stripe plan change proration service

Stripe plan change proration service

In this post you will see how to to turn off prorate on Stripe.

Stripe is a popular payment system. And very mature one. This service has a lot of built-in functionality that all contemporary businesses needs online. One example of these functionalities is subscriptions along with plans. When a subscription plan gets changed in the middle of the billing cycle, we might want to charge the client with the new plan amount only for the rest part of the current billing cycle and return the not used amount of the current billing cycle. So the price of subscription is fair and calculated daily.

For example, current plan costs 10$. Assuming the client has already paid it. The new plan costs 20$. The client switches plan in the middle of the billing cycle. The new plan daily amount for the remaining time of the current billing cycle is 1/2 of 20$, it’s 10$. As it’s a plan upgrade and thew new plan costs more, we could just charge them with these 10$. But wait, there is not used daily amount of the current plan that’s 1/2 of 10$, it’s 5$. In other words, the client has already paid some money for the remaining time of the current billing cycle. So, we deduct that money from the charge. As the result, in this example, we need to charge the client only 5$. It’s calculated as 10$ (new plan remaining time of the current billing cycle) - 5$ (already paid money for that period). This process of plan change calculations is called prorations.

Graphically it can be explained as follow:

Plan change proration

Stripe can calculate prorations for us. But that feature is available only for per-seat plans. In this post, you will see how to build a service written in Ruby from scratch that calculates prorations. It also demonstrates a ruby service object design pattern in action.


Use Ruby programming language with some tricks we come up with the following class:

class PlanChangeProration
  extend Dry::Initializer
  extend Memoist

  option :user
  option :plan_id

  def unused_time_cost
    -(unused_time_line_item&.amount || 0)

  def total
    [remaining_time_cost - unused_time_cost, 0].max


  def remaining_time_cost
    new_plan.price * 100 * new_plan_remaining_time / new_plan_billing_cycle_time.to_f

  def new_plan_billing_cycle_time
    current_plan_used_time + new_plan_remaining_time

  def current_plan_used_time
    proration_date - (unused_time_line_item&.period&.start || proration_date)

  def new_plan_remaining_time
    (remaining_time_line_item&.period&.end || new_plan_period_end) - proration_date

  def new_plan_period_end
    proration_date + (new_plan.is_yearly? ? 365.days.to_i : 30.days.to_i)

  memoize def new_plan

  # For information about upcoming_invoice
  def upcoming_invoice
      subscription_proration_date: proration_date

  memoize def customer

  memoize def subscription

  memoize def proration_date

  # Stripe always generates 2 or 3 line items for the "upcoming invoice"
  memoize def upcoming_line_items
    return [] unless subscription

  # Line item with description "Unused time on Medium Team after 16 Jun 2022" (Medium Team is current plan)
  def unused_time_line_item

  # Line item with description "Remaining time on xl_team_without after 16 Jun 2022" (xl_team_without is new plan)
  def remaining_time_line_item

And this is how to use it:

service =, new_plan_id)
service.unused_time_cost # would return 5$ in our example # also 5$, but this is the charge amount

memoist and dry-initializer made this service clean and readable.

At WideFix, we specialize in connecting Rails applications to Stripe payment systems and maintaining them for optimal performance. Our team of experts have extensive experience in integrating Stripe into Rails apps, and we will work closely with you to ensure a seamless integration. We understand the importance of having a reliable and secure payment system for your business, and we are committed to providing the highest level of support and maintenance to ensure that your Stripe integration runs smoothly. Trust us to handle all of your Stripe integration and maintenance needs, so you can focus on growing your business.

Find out more about the services we offer on our official page at

Are you seeking assistance with Ruby on Rails development?

Read also