Usage-based billing
Charging customers based on how much of your service they use is a common revenue model for SaaS businesses-this model is called usage-based or metered billing. As a business, you provide access to your service and bill your customer based on their usage at the end of the subscription cycle. Companies that use this model often also charge a flat monthly fee. At the end of the cycle, you report the usage to Stripe.
This guide describes the unique actions you need to take in your integration to support usage-based billing. It focuses particularly on:
- Setting up the pricing model and collecting and reporting usage records, two common points of friction for users.
- The simplest, lowest-effort path to implement a usage-based billing integration, preferring no-code options where available. If you need to implement usage-based billing at scale or integrate it with complex systems you can follow the same pattern but use more appropriate tools, like the Stripe API, to implement it.
Component | Description |
---|---|
Product modeling No code | Create a product to represent your service plan and configure a tiered pricing model that offers progressive, graduated pricing based on usage.
|
Customer sign-up No code | Use a Payment Link as an out-of-the-box sign-up page and payment form for your customers to subscribe to a recurring product.
|
Trials No code | Offer customers a trial of your service without accruing usage.
|
Subscription management No code | Set up the customer portal to let your customers manage their subscriptions.
|
Cancellations No code | Handle unbilled usage when metered subscriptions end.
|
Monitor subscription activity Some code | Set up webhook endpoints to listen to event notifications and handle upgrades, downgrades, payment failures, customer updates, and other scenarios.
|
Report usage Some code | Collect usage records and report them to Stripe. Learn about usage records and how to collect and report them to Stripe in this guide. |
Testing Some code | Test your integration for trial periods, webhook notifications, payment failures, and other common scenarios.
|
Sample integrations
Stripe has built two sample apps that demonstrate usage-based billing, Typographic and Pasha. This section describes how those sample apps are implemented.
Typographic, Stripe’s fictional demo app, uses a good-better-best model along with usage-based billing.
Component | Description |
---|---|
Product modeling | Typographic offers three levels of service: Starter, Growth, and Enterprise. Each level of service is represented on Stripe as a different product with associated prices. They charge a flat monthly fee for each level as part of pricing model with two graduated tiers. In the Starter plan, there is no charge for the first tier of 0-10 thousand requests. And in the second tier, there is a .01 USD charge for any request over 10 thousand. Users pay 10 USD regardless of how many requests they make. Pasha offers two levels of service: Basic and Premium. Each level of service is represented on Stripe as a different product with associated prices. They charge a flat monthly fee for each level as part of pricing model with two graduated tiers. In the Basic plan, there is no charge for the first tier of 0-2 thousand emails. And in the second tier, there is a .01 USD charge for any email over 2 thousand. Users pay 5 USD regardless of how many emails they send. Read more about pricing models: |
Customer sign-up | Both Typographic and Pasha use prebuilt Stripe Elements for parts of their customer experience, including collecting customers’ emails and billing details when they sign up for the service for the first time. Typographic uses the Card Element to securely collect card details, provide real-time validation, formatting, and autofill when customers enter their card details. See the code implementation in the sample app. Pasha also uses the Card Element to collect card details. They also use prebuilt Elements to save the payment details to a customer record, handle payment failures, subscribe customers to a pricing plan, and upgrade and downgrade plans. See the code implementation in the sample app. |
Trials | Designed to be a minimal implementation, Typographic doesn’t have robust handling for trials. Pasha listens for the In a production app, they would also need to implement logic to handle the behavior of the subscription after it ends. Read more about subscription trials and subscription webhook events. |
Subscription management | Typographic built a custom page that lets customers modify their plan, update payment details, and cancel their subscription. Pasha also built a custom account management page. You can also use Stripe-hosted resources for account management, including the customer portal and Checkout. |
Cancellations | Both Pasha and Typographic provide cancellation buttons on their sites. When users cancel their subscription in the front end, their backend calls the Subscriptions API. Here’s the frontend and backend code for Pasha. Learn how to handle cancellations and prorations in this guide. |
Monitor subscription activity | Pasha creates a webhook endpoint and listens for events about invoice status changes, cancellations, and trials ending. See an example of their webhook implementation on GitHub. Typographic does not have a webhook implementation. Read about monitoring subscriptions with webhooks in this guide. |
Report usage | Pasha’s implementation doesn’t include usage reporting. Typographic’s implementation of usage aggregation is minimal. Read about how to report usage in this guide. |
Testing | Neither Pasha nor Typographic have any demonstrable testing patterns. Read about how to test your integration in this guide. |
Usage-based billing lifecycle
Here’s what the lifecycle of a usage-based billing looks like.
This diagram illustrates what happens after you’ve implemented a customer experience.
Prerequisites
To implement usage-based pricing on Stripe, you need:
- To use Stripe Billing.
- A mechanism to track usage of your service.
- To decide whether you’re going to charge customers automatically or send invoices.
- To decide if you’re going to implement usage thresholds.
- You can use billing thresholds to cap unbilled amounts or to bill when a specified threshold is reached.
- Make sure your integration handles these events appropriately. For example, you may want to inform customers so their service isn’t interrupted unexpectedly or they’re billed unexpectedly.
Usage-based billing compared to other pricing models
With Stripe Billing, you can set up several different pricing models. Some of the most common models are flat rate, per-seat, and tiered.
In these other pricing models, you define a specific quantity when you subscribe a customer. With usage-based billing, the amount depends on the user’s activity.
Billing in arrears
If you charge a flat fee in addition to the usage, Stripe won’t charge for the flat fee until the end of the billing cycle, along with any accrued usage.
If you want to charge customers for a flat fee up front, you can create a separate product and price to represent the flat fee. If you use this approach, you can’t use the Customer portal or Stripe Checkout as they don’t support multi-item subscriptions.
Product modeling
Model your business on stripe with products and prices.
You create your products and their pricing options with the Stripe API or Dashboard. Typographic has two products, each of which has two tiers:
- Basic option
- Tier one: 15 USD per month for 2,000 emails
- Tier two: An additional .00100 USD for each email after 2,000
- Premium option
- Tier one: 75 USD per month for 10,000 emails
- Tier two: An additional .00075 USD for each email after 10,000
To achieve this kind of pricing, you charge a flat fee and an additional amount based on how much customers use. With graduated tiers, customers initially pay the flat fee for the first 2,000 or 10,000 emails. If they upload more than that, they reach tier two and start paying for each additional email. You could also charge solely based on usage without the flat fee.
During each billing period, you create usage records for each customer and then Stripe adds them up to determine how much to bill for. This process is explained in a subsequent step but understanding the default behavior might impact how you create prices.
Aggregate usage
By default, Stripe sums up the quantity
of all usage records for a customer in a billing period and then multiplies the total by the unit_amount
of the price. If you want to change this behavior, you need to set aggregate_usage when you create the price. You can read more about this in the pricing model documentation but you can choose between using:
- The last usage record sent during a billing period
- The last usage record sent regardless of billing period
- The usage record with max (highest)
quantity
during a billing period
The default behavior is used in this guide so aggregate_usage
isn’t set manually.
Customer signup
You need to create a surface to allow your customers to select a plan and enter their billing information. The easiest way to do this is with Payment Links-you don’t need to modify your site, or even use your own site. You can create a payment link configured with your product and share the link with your customers.
When a customer selects a recurring product and enters their billing information in the Payment Link, Stripe creates two records:
- Customer
- Subscription
These records are both stored within Stripe.
If you need more advanced options, there are several:
- Customer portal - Configure the portal to and share the link with your customers.
- Checkout - Add a redirect from your site to a Stripe-hosted Checkout session.
- Elements - Use customizable React elements in your site.
Trials
You can use trial periods for subscriptions with usage-based billing. During the trial period, any usage accrued doesn’t count toward the total charged to the customer at the end of the billing cycle. After the trial period ends, usage accrues and is billed at the end of the next billing cycle.
Trials and aggregate usage
If you use the aggregate_usage
parameter and set the behavior to last_ever
, your customer will be billed for the last usage record if it falls within the trial period, even if the usage occurred during the trial period.
For example, if you provide file storage you might want to offer a month of free storage, but then charge for the first month if the customer continues to store files with your service.
Learn more about trial periods and subscriptions.
Webhooks and trials
Make sure that your integration properly monitors and handles web events related to changes in trial status.
A few days before a trial ends and the subscription moves from trialing
to active
, you receive a customer.subscription.trial_will_end
event. When you receive this event, verify that you have a payment method on the customer so you can bill them. Optionally, notify the customer that they will be charged.
Status | Description |
---|---|
trialing | The subscription is currently in a trial period and it’s safe to provision your product for your customer. The subscription transitions automatically to active when the first payment is made. |
active | The subscription is in good standing and the most recent payment is successful. It’s safe to provision your product for your customer. |
incomplete | A successful payment needs to be made within 23 hours to activate the subscription. Or the payment requires action, like customer authentication. Read more about payments that require action. Subscriptions can also be incomplete if there’s a pending payment. In that case, the invoice status would be open_payment_pending and the PaymentIntent status would be processing . |
incomplete_expired | The initial payment on the subscription failed and no successful payment was made within 23 hours of creating the subscription. These subscriptions don’t bill customers. This status exists so you can track customers that failed to activate their subscriptions. |
past_due | Payment on the latest finalized invoice either failed or wasn’t attempted. The subscription continues to create invoices. Your subscription settings determine the subscription’s next state. If the invoice is still unpaid after all Smart Retries have been attempted, you can configure the subscription to move to canceled , unpaid , or leave it as past_due . To move the subscription to active , pay the most recent invoice before its due date. |
canceled | The subscription has been canceled. During cancellation, automatic collection for all unpaid invoices is disabled (auto_advance=false ). This is a terminal state that can’t be updated. |
unpaid | The latest invoice hasn’t been paid but the subscription remains in place. The latest invoice remains open and invoices continue to be generated but payments aren’t attempted. You should revoke access to your product when the subscription is unpaid since payments were already attempted and retried when it was past_due . To move the subscription to active , pay the most recent invoice before its due date. |
Learn more about subscriptions and webhooks.
Subscription management
Use the customer portal to allow your customers to modify or cancel their subscriptions. The customer portal also enables customers to view, download, and pay their invoices. Learn how to set up the customer portal.
Other options:
- Checkout - Add a redirect from your site to a Stripe-hosted Checkout session.
- Elements - Use customizable React elements in your site.
- Subscriptions API - Make calls to the API from your own site.
Cancellations
With usage-based billing, the price paid by the customer varies based on consumption during the billing cycle. When changing the billing cycle results in ending a subscription interval early, you charge the customer for the usage accrued during the shortened billing cycle.
When a subscription is canceled, it cannot be reactivated. Instead, collect updated billing information from your customer, update their default payment method, and create a new subscription with their existing customer record.
When a subscription has been scheduled for cancellation using cancel_at_period_end
, you can reactivate it at any point up to the end of the period by updating cancel_at_period_end
to false. The final invoice includes any metered usage when the subscription cancels at the end of the billing period.
Prorations
When your customer changes their subscription, there’s often an adjustment to the amount they owe known as a proration. You can use the upcoming invoice endpoint to display the adjusted amount to your customers.
On the frontend, pass the upcoming invoice details to a backend endpoint.
function retrieveUpcomingInvoice( customerId, subscriptionId, newPriceId, trialEndDate ) { return fetch('/retrieve-upcoming-invoice', { method: 'post', headers: { 'Content-type': 'application/json', }, body: JSON.stringify({ customerId: customerId, subscriptionId: subscriptionId, newPriceId: newPriceId, }), }) .then(response => { return response.json(); }) .then(invoice => { return invoice; }); }
On the backend, define the endpoint for your frontend to call. Retrieve the upcoming invoice and pass in the changes you want to preview. For this example, you need to delete the subscription item for the old price ID, clear the usage, and then add the new price ID. These changes aren’t actually applied, they just define what the preview looks like.
Monitor subscription activity
Monitor subscriptions in the Dashboard or set up webhook endpoints and listen for events. Learn more about subscriptions and webhooks.
Report usage
Throughout each billing period, you need to report usage to Stripe so that customers are billed the correct amounts. You do this by creating usage records with a subscription item, quantity
used, and a timestamp
. How often you report usage is up to you, but this example uses a daily schedule. It’s best to send usage records in batches to reduce the number of API calls you need to make.
You also have the option of calculating usage yourself or having Stripe do it. In this example, Stripe does the calculations so the action
is set
. When reporting usage, use idempotency keys to ensure usage isn’t reported more than once in case of latency or other issues.
When you report usage, the timestamp
has to be within the current billing period, otherwise the call fails. If aggregate_usage
is set to sum
on the price, there’s an additional five minutes after the end of a billing period when you can report usage (this is to accommodate for clock drift). For all other aggregate_usage
values, the timestamp has to be within the billing period.
If you need to see the usage for a customer during a current period, you can retrieve the upcoming invoice and check the quantity
for each subscription_item
.
Testing
Test your integration to make sure it behaves as you expect. Learn more about testing subscriptions integrations.
You can use to test clocks to test different scenarios, including mock usage records. When you use make a usage reporting call, you need to synch the timestamp of the test clock with the usage records. Make a note of the test clock timestamp so that your usage records fall within the same time window. Learn more about test clocks.