Usage-based pricing bills customers per unit consumed rather than a flat fee. Implementing it in Stripe takes five steps: pick one billable event, instrument it server-side, create a meter and metered price, set a base subscription with an included tier, then migrate existing customers with shadow billing. One rule above all: meter the value, not the cost.

How to Implement Usage-Based Pricing for SaaS: The 5-Step Sequence

The full sequence, before any section drills in:

  1. Pick one billable event aligned to the value your customer associates with using your product.
  2. Instrument it server-side in your app with an idempotency key and a local usage log.
  3. Create a Stripe Billing meter and metered price using stripe.billing.meters.create and stripe.prices.create.
  4. Set a base subscription with an included tier, not pure pay-as-you-go.
  5. Shadow-bill existing customers for 30-60 days before migrating anyone to the new model.

At 40-200 customers you do not need a billing platform. Stripe metered billing plus one webhook handler covers it entirely. BillingPlatform, Maxio, and Ordway are the right call when pricing complexity warrants a dedicated system, not now. Every vendor guide ranking above this one was written for procurement-stage buyers; this one is for the founder who has 40 customers on a flat-fee Stripe plan.

Shipping a pricing change this quarter? Subscribe for one teardown every Friday.

What Should You Actually Meter? Picking the Billable Event

The billable event is the single most consequential decision in usage-based pricing, and most founders get it wrong by metering cost instead of value.

A metered event is the discrete action you count and bill against: one document analyzed, one contact enriched, one agent run, one GB stored. The event you choose must map to the moment the customer perceives value delivered, not to the moment your infrastructure spends money.

Anthropic's Claude API is priced per token. The Claude.ai app is priced by subscription. Same model, two structures, because the relationship between the buyer and usage differs. If you bill per token but your customer thinks in “documents analyzed,” every invoice triggers a support ticket because the unit means nothing to them.

A quick decision table:

Value metric examplesCost metric examplesGap risk
Documents analyzedTokens consumedInvoice confusion, support load
Contacts enrichedAPI calls madeCustomers undervalue low-call jobs
Agent tasks completedCompute-seconds usedPricing looks punitive during fast jobs

Meter the unit your customer associates with getting value. OpenView's usage-based pricing research covers this alignment principle in depth.

One concession: when value and cost decouple badly (a power user generating 50x median token cost on a “per document” plan), you need a guardrail: an overage rate, a fair-use cap, or a hybrid floor. The hybrid structure is the default recommendation in Section 5.

Instrumenting Usage in Your App Before You Touch Billing

You cannot bill what you cannot count reliably. Usage instrumentation comes before any Stripe work.

Emit the event from your server at the moment the billable action completes. Never from the client side: client-side counts are spoofable and undercount on failed requests.

Three things you need in place before your first Stripe API call:

  1. Emit server-side at the moment the billable action completes (after success response, not before).
  2. Attach an idempotency key to every event. An idempotency key in the metering context is a unique ID per event that prevents double-counting when your app retries on a network error.
  3. Write to a local usage log before sending to Stripe. This log is your source of truth.

The local log is the step founders skip. Your app and Stripe will disagree at some point: a retry storm, a partial batch failure, a deploy mid-period. When that happens, the log is how you reconstruct ground truth. Without it, you are reconciling Stripe's numbers against memory.

Illustrative pseudocode for an event emit:

// illustrative: emit usage event after billable action completes
async function recordUsage(customerId, quantity, jobId) {
  // Write to local log first
  await db.usageLog.create({
    stripe_customer_id: customerId,
    quantity,
    idempotency_key: `job_${jobId}`,
    recorded_at: new Date(),
  });

  // Then report to Stripe
  await stripe.billing.meterEvents.create({
    event_name: 'documents_processed',
    payload: {
      stripe_customer_id: customerId,
      value: String(quantity),        // must be a string
    },
    identifier: `job_${jobId}`,       // idempotency key
  });
}

Wiring Stripe Metered Billing: The Build

Metered billing in Stripe means you report usage against a metered price during the billing period, and Stripe invoices the aggregate at period close.

One thing worth flagging before the code: Stripe removed createUsageRecord in April 2025. Any tutorial still using subscriptionItems.createUsageRecord() is stale. The current API is stripe.billing.meterEvents.create. Stripe's usage-based pricing guide is the canonical reference.

Create the Meter and Metered Price

A Stripe Meter is the named aggregation rule for a usage event type: which event name to watch and how to sum it within a billing period.

Step 1: Create the meter.

// illustrative
const meter = await stripe.billing.meters.create({
  display_name: 'Documents processed',
  event_name: 'documents_processed',   // must match exactly in meterEvents.create
  default_aggregation: {
    formula: 'sum',                    // 'sum' | 'count' | 'last' (use 'sum' for most models)
  },
  customer_mapping: {
    event_payload_key: 'stripe_customer_id',
    type: 'by_id',
  },
  value_settings: {
    event_payload_key: 'value',
  },
});
// meter.id looks like 'mtr_...'

The aggregation formula is sum, count, or last. There is no max option. For most models, sum is what you want: total units consumed in the period.

Step 2: Attach the meter to a metered Price.

// illustrative
const price = await stripe.prices.create({
  currency: 'usd',
  unit_amount: 13,                     // $0.13 per unit (in cents)
  recurring: {
    interval: 'month',
    usage_type: 'metered',
    meter: meter.id,
  },
  product: 'prod_...',
});

For an included-tier structure, set billing_scheme: 'tiered' on the price. The first N units at $0, then per-unit above the threshold. Stripe handles the “included allowance plus overage” math natively.

Alternatives worth naming once: Lago is open-source and self-hostable for more complex aggregation needs. Metronome and Orb are usage-billing platforms for when your model outgrows Stripe. Neither is necessary at 40 customers.

Report Usage Events and Reconcile

Step 3: Report meter events from your usage log.

// illustrative: report usage after local log write
await stripe.billing.meterEvents.create({
  event_name: 'documents_processed',
  payload: {
    stripe_customer_id: 'cus_...',
    value: '1',                        // string, not number
  },
  identifier: 'evt_' + yourUniqueId,  // idempotency key
});

Stripe also exposes a v2 high-throughput path (/v2/billing/meter_event_stream) for up to 10,000 events/second. At your stage, meterEvents.create is enough.

Reconcile your local log against Stripe's recorded usage at least daily. Pull stripe.billing.meters.retrieve(meter.id) with a time range and diff against your log totals. This is the step that separates founders who have clean billing from founders who are apologizing in the support inbox. A silent drift becomes a customer-facing overcharge, and a bootstrap customer with your personal email will not wait patiently after a 3x invoice.

How Do You Set the Price and the Included Tier?

Pricing the unit is a margin problem and a psychology problem. Solve both at once.

The math (illustrative, not a market quote): Take your per-unit wholesale cost (model inference plus infrastructure). Say it is $0.04 per document and you want 70% gross margin. List price: $0.04 / (1 - 0.70) = $0.13. AI-native SaaS gross margins typically run 60-75% because variable inference costs compress the floor. Run this for your own unit cost before publishing a price.

60-75%
AI-native SaaS gross margin

AI-native SaaS gross margins typically run lower than traditional SaaS because variable inference costs sit in COGS and compress the floor. Price the unit for margin, and revisit it monthly as upstream model costs move.

SaasFlywheel pricing research; see the pricing-models decision framework

Mismatch between cost basis and pricing model is the leading margin-collapse risk for AI-native SaaS. If your upstream model cost doubles and your metered price is fixed, you absorb the full delta.

The psychology problem: the included tier. Pure pay-as-you-go with no floor is the most common pricing mistake for early SaaS. It makes revenue unforecastable and lets a customer drop to $0 without churning (zombie accounts that never expand). A small floor fixes both.

A base subscription with an included allowance: $30 per month includes 300 documents, additional at $0.13 each. Light users pay a predictable amount. You get baseline MRR plus expansion from heavy users. Hybrid model structures have become the dominant pattern in SaaS usage-based pricing as pure pay-as-you-go proves hard to forecast.

For the full model comparison (pure per-unit vs. hybrid vs. per-seat), see the pricing-models decision framework on SaasFlywheel.

Migrating Existing Customers Without Triggering a Churn Spike

No top-10 result for this query walks the migration. That gap is exactly why this section exists.

Three definitions upfront. Grandfathering means letting existing customers keep their current price after you change pricing. Price migration is the deliberate process of moving them to the new model. Shadow billing means running the new meter in parallel for 30-60 days, computing what each customer would pay, with no charge going out yet.

Grandfathering everyone indefinitely is the safe-looking choice that quietly caps your expansion revenue for years. A hard forced migration on short notice manufactures a churn spike, the opposite of catching churn risk early. The answer is a staged migration.

  1. Shadow-bill for 30-60 days

    Turn on the meter. Do not attach it to billing. Log what each customer would have been charged. This converts the migration from a guess into a data-backed decision.

  2. Segment by impact

    You have three cohorts after the shadow period: pays less, pays same, pays more. The revenue distribution tells you where the risk sits.

  3. Migrate the pays-less-or-same cohort first

    Email each customer their projected invoice from the shadow period. For most, it is lower than their current flat fee. This cohort migrates without friction and gives you proof before you tackle the harder segment.

  4. For the pays-more cohort: grandfather the floor, give 60-90 days notice, migrate at renewal

    “We are moving you at renewal” lands differently than “your price changes in 30 days.” Offer a grandfathered base price plus the included tier as the transition structure.

Shadow billing converts migration from an announcement into a data conversation. Instead of “pricing is changing,” you send each customer their actual projected invoice: “Based on your usage last month, your bill would be $X.” That framing removes most of the anxiety.

At 40-200 customers, emailing everyone personally is feasible and something a billing platform serving 10,000 accounts cannot replicate. This is one of the real advantages of being small: you can have a human conversation about a pricing change rather than mass-broadcasting to a segment. A well-run migration typically sees single-digit percentage churn. The customers who leave at fair terms would likely have churned anyway.

What Breaks in Production (and How to Catch It Early)

Usage-based pricing moves billing risk from a monthly concern to a continuous one. Three failure modes matter most.

Failure mode 1: metering drift. Your app and Stripe disagree on the count during retries, deploy windows, or partial batch failures. Catch it via daily reconciliation (local log vs. Stripe meter totals) with an alert when the delta exceeds 1%. As Lago notes, inaccurate metering is a leading cause of revenue leakage from billing errors. The drift cuts both directions: overcharge or silent undercharge. Daily reconciliation catches both.

Failure mode 2: invoice shock.A customer's usage spikes; their next invoice is 5x. You find out when they reply to the receipt email at 2 AM. Set usage alerts at 80% of the included tier, one to the customer and one to you. A spending cap option, where usage pauses instead of billing infinitely, converts invoice anxiety into a trust signal.

Failure mode 3: cost-basis spike. Upstream model or infrastructure costs rise; your metered price no longer clears target margin. AI-native SaaS gross margins typically run 60-75% (lower than traditional SaaS) because inference costs vary per customer. Monitor per-unit gross margin monthly, not quarterly. By the time a quarterly review surfaces the problem, you have billed three months at the wrong price. The SaaS metrics monitoring framework covers this in detail.

Your First Week: A Shippable Checklist

Pick one of these items and start today. By Friday you should have at least the first three done.

  • Pick one billable event aligned to the value your customer gets, not to your infrastructure cost.
  • Instrument it server-side with an idempotency key and a write to a local usage log before the Stripe call.
  • Create the Stripe meter and metered price using stripe.billing.meters.create (aggregation: sum) and stripe.prices.create with usage_type: 'metered'.
  • Set a base subscription plus included tier, not pure pay-as-you-go. Pick a floor that covers billing ops cost on small accounts.
  • Start shadow-billing existing customers for 30 days. The meter runs; no charges go out yet.
  • Draft the migration emailsegmented by projected impact. Write three versions: one for the “pays less” cohort, one for “pays same,” one for “pays more.”

You do not need to complete the migration this week. Start the shadow period now so you have data in 30 days.

If you have not yet decided whether usage-based pricing is the right model for your product, start with the pricing-models decision framework before building anything.

We publish one SaaS pricing teardown every Friday. Subscribe to get the next one.