Skip to content
Tech Stack12 June 2026 · 7 min readUpdated 30 September 2026

Building Usage-Based Billing with Stripe Metering in 2026

Stripe usage-based billing in 2026: when Billing Meters still fit, how meter events, limits and errors behave, and where Stripe now points new integrations.

Building Usage-Based Billing with Stripe Metering in 2026

What you'll learn

  • Is Stripe usage-based billing with Billing Meters still the right starting point?
  • How do Stripe billing meter events work?
  • How do you report meter events at scale without losing revenue?
Article contents

You're adding metered pricing to a SaaS and wondering whether to wire up Stripe's Billing Meters or something newer. Start by reading the first section below against your own pricing sheet, because Stripe's own guidance changed: for new usage-based integrations its docs now point to Metronome, not to Billing Meters.

This guide covers where Stripe usage-based billing with Billing Meters still fits, how meter events behave (limits, errors, corrections), and what to show customers while usage accumulates. Everything here was checked against Stripe's documentation on 30 September 2026. It sits inside the wider SaaS billing and payments guide.

Is Stripe usage-based billing with Billing Meters still the right starting point?

Only if your pricing is plain pay-as-you-go and you already bill through Billing Meters; for new integrations, Stripe's documentation says to use Metronome, its primary usage-based billing platform.

The same page lists the cases where Metronome is the recommended route: starting from scratch, adding usage-based pricing to existing flat-rate subscriptions, prepaid credits, enterprise commits, dimensional pricing, real-time usage visibility and high-volume ingestion. Stripe adds that basic usage-based billing "remains fully supported" and that existing Billing Meters users don't need to migrate. The comparison page puts the difference in a table:

CapabilityBilling Meters (basic)Metronome
Pay-as-you-go, flat fee plus overageSupportedSupported
Prepaid credits with real-time drawdownNot supportedSupported
Enterprise commits, minimums, rampsNot supportedSupported
Dimensional pricingNot supportedSupported
Real-time usage visibilityNot supportedSupported
Connect, Adaptive Pricing, WorkflowsSupportedNot supported
CheckoutSupportedLimited

Why does this matter for pricing? Usage-based models are attractive partly because buyers ask for them. An IDC survey of more than 1,000 IT professionals, reported by CIO.com in January 2025, found that 46% named unpredictable pricing as a primary obstacle to implementing generative AI, and respondents preferred pay-as-you-go consumption over upfront commitments. That is a survey of AI buyers, so treat it as a signal for AI-shaped products rather than for every SaaS.

When is a flat fee the better answer?

If usage doesn't track the value you deliver, don't meter at all. BookBed (Flutter, Firebase and Stripe) has subscriptions wired up, not yet activated for paid traffic, and no metering layer, because nothing in its pricing needs one. The question to ask is whether consumption matches customer value better than a seat or tier does. If the answer is "maybe", start flat and add metering once you have evidence. The Supabase and Stripe stack page and the subscription pattern post cover the flat-subscription baseline for a typical B2B SaaS.

What about Lago and other tools?

Open tooling exists if you want to own the billing logic. Lago's documentation describes deduplicating re-sent events through a transaction_id and running self-hosted. This guide doesn't benchmark it, so no throughput figures are quoted. Before adopting any second system, list what you'd give up: Stripe's comparison above shows Metronome gives up Connect support, and any extra billing layer means another service to run and reconcile.

How do Stripe billing meter events work?

A Billing Meter names an event, aggregates the values you report with sum, count or last, and a metered price bills that aggregate on each subscription invoice.

A tall tower of stacked concrete cubes with a single bright cyan cube at the top, warm beige backdrop, dramatic diagonal light

The implementation guide walks through three objects: a meter, a metered price attached to it, and a subscription. You create the meter once:

curl https://api.stripe.com/v1/billing/meters \
  -u "$STRIPE_SECRET_KEY:" \
  -d "display_name=API tokens" \
  -d event_name=api_tokens \
  -d "default_aggregation[formula]=sum" \
  -d "customer_mapping[event_payload_key]=stripe_customer_id" \
  -d "customer_mapping[type]=by_id" \
  -d "value_settings[event_payload_key]=value"

Then you attach it to a price with recurring[usage_type]=metered and recurring[meter], and report usage as meter events. Stripe's migration guide states that the legacy usage records APIs were removed in API version 2025-03-31.basil and that metered prices must be backed by meters from that version on. Any tutorial that sets usage_type: 'metered' without a meter is out of date.

Two behaviours are easy to miss. Meters exist independently of subscriptions, so the same migration guide notes you can collect usage before a customer has a subscription and track many customers on one meter. And max aggregation is not supported.

Why is the meter configuration effectively permanent?

Once a meter is configured you can't change anything except its display name, according to the meter configuration docs.

A glowing cyan disc pressed into a pale clay tablet, leaving a circular permanent impression, warm beige background

That covers the event name, aggregation formula and the payload keys for customer and value. Each event name can only be used with one meter. If you realise count should have been sum, you create a new meter and move subscribers to a new price, which is a migration during a live billing period. So rehearse in a sandbox first: send events with realistic payloads, preview the invoice, and try edge cases such as zero values, very large values and payloads missing the value key. Stripe's error codes include meter_event_value_not_found and meter_event_invalid_value, so those cases do surface, just asynchronously.

The configuration page also describes two ingestion modes. Raw mode treats every event as standalone. Pre-aggregated mode keeps only the most recent event in each hourly or daily window, so a newer event overwrites the previous one. Pick deliberately, because the choice changes what a retry does.

How do you report meter events at scale without losing revenue?

Send a deterministic identifier with every event, pre-aggregate where volume demands it, and listen for Stripe's asynchronous error events, because Stripe validates meter events after it accepts them.

A folded paper channel guiding a line of concrete spheres in single file, with one bright cyan sphere at the leading edge under stark directional light

Here are the limits and behaviours from the recording usage documentation and the meter event API reference, as of this writing:

TopicWhat Stripe documents
Standard rate limit1,000 calls per second per account in live mode, plus one concurrent call per customer per meter
High-throughput stream (API v2)Up to 10,000 events per second, live mode only; contact sales for up to 200,000; auth tokens valid for 15 minutes
Timestamp windowWithin the past 35 calendar days, at most 5 minutes in the future
Identifier uniquenessEnforced within a rolling period of at least 24 hours
Dimension cardinality10,000 unique combinations per meter per hour; 100 per customer per meter overall
Decimal valuesAccepted; negative overall usage shows as 0 on the invoice

Why does the identifier matter?

If you don't pass an identifier, Stripe generates one, so a client that retries after a timeout sends a second event that looks new. Derive the identifier from something that's identical on retry, such as your internal request ID or a hash of the usage record. Stripe's reference recommends UUID-like values and notes the uniqueness check mainly targets accidental retries within very short intervals, so it isn't a substitute for your own deduplication over longer periods.

How do you handle errors and late events?

Stripe processes meter events asynchronously and creates error events when something is wrong. The documented event types are v1.billing.meter.error_report_triggered and v1.billing.meter.no_meter_found, both delivered as thin events, and the error codes include timestamp_too_far_in_past, timestamp_in_future and meter_event_dimension_count_too_high. Subscribe to them in a webhook endpoint on day one, alert a human, then correct and resend the invalid events.

Usage reported after a period ends has a documented window. Invoices get a default finalization grace period of one hour, configurable up to 72 hours, and only subscription-cycle and schedule-phase invoices pick up usage reported during it, per the grace period docs. Usage reported after the grace period isn't included on that invoice. Decide your own cutoff for late events and write it down.

For mistakes, you can cancel events sent within the last 24 hours with a meter event adjustment, or record negative quantities. Canceling usage already on a finalized invoice doesn't update that invoice.

When should you pre-aggregate?

Stripe's own advice for high volume is to accumulate usage and send one aggregated event periodically, or move to the v2 stream. A sound pattern is a durable queue on the hot path, a background job that groups events per customer, and deterministic identifiers on each flush. The flush interval is your call; I'd start with something a human can reason about, like every minute, and raise it only if you approach the rate limit. That is my recommendation, not a Stripe figure.

What should customers see while their usage accumulates?

Show them your own live counter, and use Stripe's meter event summaries to reconcile against what will be invoiced.

The Meter Event Summary API returns aggregated usage for a customer, meter and time window:

curl -G https://api.stripe.com/v1/billing/meters/$METER_ID/event_summaries \
  -u "$STRIPE_SECRET_KEY:" \
  -d customer=$CUSTOMER_ID \
  -d start_time=$PERIOD_START \
  -d end_time=$PERIOD_END

Stripe warns that summaries and upcoming invoices might not immediately reflect recent events, because processing is asynchronous. Its own comparison table lists real-time usage visibility as unsupported in basic usage-based billing. So if customers need a number that moves as they work, keep a parallel counter in your own store and treat Stripe's summary as the billing record. Show the gap honestly instead of displaying zero while the invoice says otherwise.

Two more Stripe features reduce bill shock. Usage alerts fire when a customer crosses a meter threshold, with a maximum of 25 alerts per meter and customer combination. Billing credits cover prepaid or promotional usage, but they're applied only when an invoice finalizes, so customers can exceed their balance mid-cycle. That caveat is exactly why Stripe steers prepaid-draw-down designs to Metronome.

Wire meter errors, invoice events and subscription changes into one handler rather than several, and keep the broader Stripe integration in a single place. Your next step: in a Stripe sandbox, create one meter, send three events with fixed identifiers, resend one of them, and check whether the summary counts it once. Which of your real usage events would have no stable identifier to pass?

Free resource

Free SaaS MVP Scope Template

A Notion document with the full feature checklist, MVP vs. nice-to-have table, pre-build questions, and cost signals — so you walk into any developer call knowing exactly what to ask for.

Get the template →
DL

Dusko Licanin

Full-Stack Developer · Banja Luka, Bosnia

Full-stack developer shipping SaaS MVPs, web apps, and mobile apps using AI-augmented workflows — without agency coordination overhead. Live portfolio: BookBed, Callidus, Pizzeria Bestek.

Frequently Asked Questions

What is Stripe usage-based billing and who should use Billing Meters?

Stripe usage-based billing charges customers for what they consume by recording meter events against a meter and billing the aggregate on a subscription invoice. For new integrations, Stripe's documentation says to use Metronome, its primary usage-based billing platform, and to keep Billing Meters for existing integrations with straightforward pay-as-you-go pricing. Metronome adds prepaid credits, enterprise commits, dimensional pricing and real-time usage visibility, while Billing Meters keeps compatibility with Connect and Checkout. Compare Stripe's feature table with your pricing sheet before choosing, because moving from one path to the other later costs real engineering effort.

How does Stripe handle idempotency for meter events?

Every meter event accepts an identifier, and Stripe enforces uniqueness on it within a rolling period of at least 24 hours. If you omit it, Stripe generates one, so a client retry after a timeout becomes a second billable event. Derive the identifier from something identical on retry, such as your request ID, transaction ID or a hash of the usage record. Stripe's reference says the check mainly targets accidental retries within very short intervals, so keep your own deduplication for longer horizons. Events sent in the last 24 hours can be canceled with a meter event adjustment, and negative values can correct usage.

Can I change a Stripe billing meter after creating it?

No, once a meter is configured you cannot change anything except its display name. The event name, aggregation formula and the payload keys for customer and value are fixed, and an event name can only be used with one meter. To change any of them you create a new meter and move subscribers to a new price, which is a migration during a live billing period. Rehearse in a sandbox first: send realistic payloads, preview the invoice and test edge cases such as zero values, very large values and payloads missing the value key.

What happens to late or invalid Stripe meter events?

A meter event timestamp must be within the past 35 calendar days and no more than 5 minutes in the future, and Stripe validates events asynchronously. Problems surface as v1.billing.meter.error_report_triggered or v1.billing.meter.no_meter_found events with codes such as timestamp_too_far_in_past or meter_event_dimension_count_too_high. Invoices have a default finalization grace period of one hour, configurable up to 72 hours, during which subscription-cycle invoices pick up late usage. Usage reported after that is not included on that invoice, so set your own cutoff for late events and alert on the error events.

What are the Stripe billing meter events rate limits?

The standard meter event endpoint allows 1,000 calls per second per Stripe account in live mode, plus one concurrent call per customer per meter. The API v2 meter event stream supports up to 10,000 events per second in live mode, with up to 200,000 available by contacting sales, and its authentication tokens are valid for 15 minutes. Stripe suggests pre-aggregating usage, for example sending one aggregated event periodically instead of one per action, before reaching for the stream. Dimension limits are separate: 10,000 unique combinations per meter per hour and 100 per customer per meter.