Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prorate metered plan in Stripe

We're looking to charge per user in our SaaS. We're using Stripe as our payment processor. The first 5 members are included as part of the base plan. Any excess users are charged an extra free (let's say $10).

If a user is added halfway through the billing period, we'd only want to charge them $5. If they're added 3/4 of the way, they should be charged $7.50. If a user is added for 1/3 of the month and then deleted, they should be charged $3.33.

This is similar to Slack's approach:

Add new members to a paid workspace If you’re on a paid plan and add new members partway through the billing cycle, we’ll only charge for the cost of the time used. We’ll keep track of this for you, and bill you at the end of each month.

Here’s an example:

Let’s suppose your workspace is on the Standard plan paying monthly, which costs $8 per member per month. You add a new member 10 days into your billing period, leaving 20 days remaining in the month.

The prorated subscription cost is calculated by dividing the cost per member ($8) by the number of days in the month (30) and multiplying it by the number of days remaining (20), which gives us the prorated subscription cost for the remainder of that billing period: $5.33

If you pay annually, it works the same way. We'll calculate the prorated cost for the rest of the year, and bill you at the end of the month for any new additions.

I was wondering if that could be achieved in Stripe.

like image 999
NRaf Avatar asked Oct 17 '25 10:10

NRaf


1 Answers

Short Answer

I see some misunderstanding about what Stripe's metered plans are intended for. They stand for a kind of complete action or some work done, such as if your service created some content or performed some other work. In this case, it doesn't matter at which point of the billing cycle the work is performed and that doesn't affect its cost.

Stripe doesn't allow prorating for metered usage at the time I'm writing this comment. So if the usage of something has been logged to Stripe using a metered price, doesn't matter at which point of a billing cycle, it can either be removed without being billed (using clear_usage: true when removing a corresponding SubscriptionItem) or it will be billed in full at the end of the billing cycle.

Detailed Answer

We were facing the same issue and here's how we eventually designed and implemented our billing (simplified for readability).

In our application, we use multi-price subscriptions, where some products represent "Plans" while others represent "Add-Ons".

Let's assume your users can add "Members" and the number of members is limited for each "Plan".

The products in Stripe that define the "Plans" are as simple as:

  1. Product Hobby (5 members, metadata: { type: plan, tier: hobby })
    • Price Monthly $99/mo
  2. Product Agency (20 members, metadata: { type: plan, tier: agency })
    • Price Monthly $299/mo
  3. Product Enterprise (100 members, metadata: { type: plan, tier: enterprise })
    • Price Monthly $999/mo

The products that represent the "Add-On", such as:

  • Product Team Members (metadata: { type: add-on })
    • Price none (let's assume Hobby-tier users can't add extra members)
    • Price Seat (Agency) (metadata: { tier: agency })
    • Price Seat (Enterprise) (metadata: { tier: enterprise })

Note

You can see "Plan" products have just one price, while "Add-On" products have multiple prices, one for each tier. The type and tier metadata helps you to match "Plans" and suitable "Add-Ons" in the back-end.

These "Add-Ons" can use the Graduated model. For example, if your Agency "Plan" includes 20 seats, and then you want to charge $10 per seat per month, your Team Members Price for the Agency tier would look like this: enter image description here

When creating a subscription it includes two prices:

  1. Product Agency
    • Price Monthly $299/mo
  2. Product Team Members
    • Price Seat (Agency)

In the application, you can have a slider or a text field (GitHub way) where users can add/remove additional seats. If a user adds one more member on the 1st day of the billing cycle and removes it halfway through, Stripe (depending on the subscription settings) will automatically prorate this and charge $5 instead of $10. This way it is possible to change the number of seats on demand and users pay only for the used amount of time. You can also adjust the quantity yourself (Slack way) when the user adds/removes members. All you need to do is to update the quantity on the SubscriptionItem. Stripe will do the rest.

The important part to understand is that this logic has to be implemented in your application. When a user removes a member or a member becomes inactive (what Slack does) you should update the subscription and change the quantity. Once the member becomes active the quantity has to be adjusted again. It is possible to configure the subscription in Stripe and provide the behavior, whether to invoice immediately or at the end of the billing cycle (the user will receive a detailed invoice for extra cost). Considering the Slack behavior and to avoid lots of invoices being initiated, the second option is preferable.

In case the user wants to upgrade, let's say to Enterprise, you will need to update the subscription accordingly, and change the price for both "Plan" and "Add-On". This is done by updating SubscriptionItems and replacing the price ID on them. Stripe will do the rest of the work for you.

In case of downgrade, let's say to Hobby, where the user doesn't have the option to buy extra seats, you will need to remove the Add-On from the subscription by removing the corresponding SubscriptionItem. And again, Stripe will do all prorations for you and the user will be billed for the usage appropriately.

More About Metered

We also use metered "Add-Ons" in a similar way, with several "included" operations, and then bill using different models, such as graduated, package, and volume. Since proration doesn't apply and we don't want to generate unnecessary invoices in the middle, if a user downgrades to a tier where "Add-On" is not available, we remove it from our subscription in the back-end but keep it in the subscription in Stripe till the end of the billing cycle. This way "Add-On" becomes unavailable to the user in our application but we preserve the usage until it's paid. When the billing cycle shifts, Stripe charges for the logged usage, resets it, and then we can remove those leftover Add-Ons from the subscription in Stripe (using webhook notifications).

like image 127
Alexander S. Avatar answered Oct 21 '25 12:10

Alexander S.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!