How To Implement Usage-Based Pricing with Stripe?Comprehensive guide to translating SaaS packaging and pricing into Stripe


Engineers often get confused about how to model SaaS products’ pricing and packaging with Stripe. This can be even more difficult for people new to Stripe and having usage-based pricing scenarios. As Stripe was designed to be generic enough for physical and software goods, engineers must tailor entities to their specific use case. By the end of this guide, you will master translating SaaS pricing and packaging concepts into Stripe entities.
Our Example
To illustrate, we'll use a hypothetical Twilio-like API-driven SMS/MMS-sending service as our case study. This example will help clarify how to translate various pricing and packaging concepts into Stripe and implement usage-based pricing effectively.
Hobby | Pro | |
---|---|---|
Base Fee | $99/m | $249/m |
SMS Included | 20,000 | 100,000 |
SMS Send ($/SMS) | $0.005 | $0.004 |
MMS Send ($/MMS) | $0.015 | $0.01 |
Annual discount | 20% | 20% |
The upcoming sections will cover the key points to translate the pricing table above into Stripe following these steps:
- Defining products and prices for our line items (SMS, MMS)
- Applying tiered pricing for our plans' included SMS
- Using meters to manage prices
- Packaging prices for customers and subscriptions
- Reporting usage
Products and Prices
Everything in Stripe starts with Product and Price entities. The product word is often synonymous with the software sold in the SaaS world. But in Stripe, a Product is the smallest entity that can be priced. In our example, SMS is one product, and MMS is another. Products can have single or multiple prices, depending on various factors such as:
- Different plans (Hobby vs. Pro)
- Different currencies (USD, Eur, etc.)
- Different billing cycles (Monthly, Annual, etc.)
- Experimenting with pricing or grandfathering old customers
Prices can also be one-time fees, for example, an installation fee or recurring, which is billed for every current and future billing period. In our example, all prices are recurring, monthly, or annually.
We have two Stripe products: SMS and MMS, each with different recurring prices for the Hobby and Pro plans. Moreover, we offer a 20% discount on annual subscriptions, necessitating two more permutations for monthly and annual subscriptions. Hence, we define 2 Products (SMS, MMS) _ 2 Plans (Hobby, Pro) _ 2 Billing Periods (Monthly, Annual) = 8 Prices in total.


Note: If your business operates in multiple currencies, you will need to duplicate prices for each of them.
We also need to account for the base fee and the included SMS. There are multiple ways to do this. For simplicity, we'll include them in the SMS price as a zero-fee first tier in the next chapter, but alternatively, you could define a new product and prices just for the base fee.
Per Unit and Tiered Pricing
Stripe's recurring prices can be set per unit or using tiered pricing. With Stripe’s tiered pricing, you can define the price per unit or volume. This also allows us to describe included units and more complex pricing structures like volume-based or graduated pricing.
For example, here's how we would describe the 20,000 SMS included in the Hobby plan using tiered pricing:
First Unit | Last Unit | Per Unit | Flat Fee |
---|---|---|---|
0 | 20,000 | - | $99 |
20,001 | ∞ | $0.005 |


Licensed and Metered
Stripe's recurring price usage type can be set to licensed
or metered
.
It's set to licensed by default, meaning the customer always pays for the same quantity regardless of usage.
For usage-based pricing, this must be set to metered
, and the customer’s consumption (usage) needs to be reported.
For instance, here's how we can set the Stripe price object to reflect this:
{
id: 'price_xxx',
object: 'price',
billing_scheme: 'tiered',
currency: 'usd',
product: 'prod_OHWPWbAhIdEpq4',
recurring: {
aggregate_usage: 'sum',
interval: 'month',
interval_count: 1,
trial_period_days: null,
usage_type: 'metered'
},
tiers: [
{
flat_amount: 9900,
flat_amount_decimal: '9900',
unit_amount: null,
unit_amount_decimal: null,
up_to: 20000
},
{
flat_amount: null,
flat_amount_decimal: null,
unit_amount: null,
unit_amount_decimal: '0.5',
up_to: null
}
],
tiers_mode: 'graduated',
type: 'recurring',
unit_amount: null,
unit_amount_decimal: null,
...
}
Packaging and Customer Subscriptions
In the previous chapters, we defined our products and prices to describe our example pricing table in Stripe.
Now it’s time to package them for our customers with Stripe’s subscription entity.
In Stripe, you can assign one or many subscriptions to a customer. A Subscription
defines, for example, the billing period and frequency.
It also has a billing anchor to tell Stripe which day the subscription needs to switch the billing cycle.
The part we will focus on now is the packaging which is described in Stripe via the SubscriptionItem
entity.
A SubscriptionItem
is essentially a single price with a corresponding product. For example, SMS Hobby Monthly price.
If a price is licensed, this is also where we can define the licensed quantity. Our prices are usage-based (metered), so we won’t need to define quantity.
For example, when we start a monthly Hobby subscription for our customer, the Subscription
and its items would look the following:
const subscription = await stripe.subscriptions.create({
customer: 'cus_O7paI94y4zKm1q',
items: [
// SMS Hobby Monthly Price ID
{ price: 'price_1NLZvGLvyihio9p5V3w373xd' },
// MMS Hobby Monthly Price ID
{ price: 'price_1NLZvGLvyihio9p5V3w373xd' },
],
});


It makes sense, but worth noting that the subscriptions’ billing period has to match the price’s recurring interval. For example, you can only add monthly prices to monthly subscriptions.
Reporting Usage
Finally, it's crucial to report the customer's usage accurately.
In Stripe, usage reporting is done at the SubscriptionItem
level.
You can either increment the usage or set a new total value. Stripe has rate limits for usage reporting,
so it's often more practical to meter usage separately and report the total amount to Stripe periodically:
await stripe.subscriptionItems.createUsageRecord('my_subscription_item_id', {
quantity: 100,
timestamp: 'now',
action: 'set',
});
To avoid issues with rate limits and accuracy, we recommend using OpenMeter to measure usage and report it to Stripe. Also, check out our Stripe example on GitHub.
Summary
In conclusion, while implementing usage-based pricing with Stripe may seem challenging,
understanding the process and the right tools can simplify it greatly.
Remember, the key is to accurately translate your pricing model into Stripe's Product
, Price
, and Subscription
entities.
Checkout OpenMeter’s demo, where we build usage-based pricing with Stripe from scratch: OpenMeter.io Stripe Usage-Based Pricing Tutorial.
