Home » Usage-Based Pricing — Charge Customers for What They Consume » Usage-Based Billing for SaaS: How It Works (2026 Guide)
Usage-Based Billing for SaaS: How It Works
Usage-based billing is a five-stage pipeline: capture an event when a customer consumes something, ingest it into a metering system, aggregate it over a billing period, rate it against a price, and invoice the result. Each stage has failure modes that are invisible until a customer disputes a bill.
This page covers the mechanics — the data model, the guarantees a metering system has to provide, and the specific edge cases that break implementations. It does not cover whether you should use usage-based pricing (see What It Is and When to Use It) or which vendor to pick (see the implementation guide).
The five stages
Every usage-based billing system, regardless of vendor, implements the same pipeline. Stripe’s own documentation describes its lifecycle in four parts — ingestion, product catalog setup, billing, and monitoring [1] — which maps onto the five stages below once you separate capture from ingestion.
Stage
What happens
Where it breaks
1. Capture
2. Ingest
3. Aggregate
4. Rate
5. Invoice
Stage 1: Capture
A usage event is a record that a specific customer consumed a specific quantity of a specific thing at a specific time. In Stripe’s model, a meter event carries an event name matching a configured meter, a customer identifier, a numerical value, an optional timestamp, and an optional unique identifier for idempotency [1].
The design decision that determines most downstream pain is what you count. Three properties matter:
- Attributable — every event must resolve unambiguously to one billing entity. If your product has organizations, teams, and projects, decide now whether billing happens at the organization level or below it.
- Immutable — the event records what happened, not what you currently believe the customer is entitled to. Entitlement is a rating concern, not a capture concern.
- Idempotent at the source — generate the unique identifier in your application, not in the transport layer. Stripe enforces identifier uniqueness within a rolling period of at least 24 hours, and recommends UUID-like identifiers [2].
Stage 2: Ingestion
Ingestion is where correctness is won or lost. Four mechanics govern it.
Raw vs pre-aggregated. Stripe supports two ingestion modes. In raw mode, every event is standalone and multiple events at the same timestamp all count toward aggregation — this is the default. In pre-aggregated mode, you send one event per time interval and a newer event within the same hourly or daily window overwrites the previous one [3]. Choosing wrong here is expensive: pre-aggregated mode silently discards data you thought you were accumulating.
Idempotency keys. Every meter event maps to an identifier you can specify; if you omit it, Stripe generates one [4]. Because Stripe processes events asynchronously and networks retry, you must assume every send could arrive twice.
Timestamp windows. A meter event’s timestamp must fall within the past 35 calendar days or up to 5 minutes in the future [2]. The 5-minute allowance exists for clock drift between your servers and Stripe’s [4]. But accepting an event is not the same as billing for it — Stripe may accept an event after an invoice finalizes and include it in usage summaries without adding it to any invoice [4].
Throughput limits. The Meter Event endpoint in live mode is limited to 1,000 calls per second per account, and to one concurrent call per customer per meter [4]. Stripe’s API v2 meter event streams raise this to 10,000 events per second, with a path to 200,000 per second via sales [4]. If you expect to exceed the base limits, Stripe’s recommended mitigation is to pre-aggregate before sending — accumulate usage across many actions and send one event periodically [4].
There is also a dimension cardinality limit that catches teams off guard: Stripe accepts up to 10,000 unique dimension payload combinations per meter per hour, and only 100 unique combinations per customer per meter [4]. Events that introduce a new combination past either ceiling are rejected with the error code meter_event_dimension_count_too_high [4].
Stage 3: Aggregation
A meter defines how events roll up. Stripe offers three aggregation formulas: Sum (total of all values in the period), Count (number of events), and Last (value of the most recent event) [3].
The critical constraint: once a meter is configured, you cannot change anything except its display name [3]. Event name, ingestion mode, and aggregation formula are permanent. If you configure a meter as Count and later need Sum, you are creating a new meter and remapping prices.
Two correction mechanisms exist, and both have sharp edges:
- Meter Event Adjustments cancel previously recorded events, but only events sent within the last 24 hours. If the usage already appears on a finalized invoice, Stripe will not update that invoice or issue a corrected one [3].
- Negative quantities are accepted. If total cycle usage nets to negative, the invoice line item reports quantity as 0 [3].
Stage 4: Rating
Aggregated quantity meets a price. This is where hybrid models get their arithmetic: included allowance is subtracted from total usage, the remainder is multiplied by the overage rate, and tiered pricing applies a different rate to each usage band.
Two things to know about how Stripe handles this:
Credits reconcile at invoice time only. With basic usage-based billing, credit-based pricing is settled when the invoice is generated, not in real time — which means a customer can exceed their credit balance during the billing cycle [5]. Real-time credit burndown is one of the capabilities Stripe lists as Metronome-only [5].
Mid-cycle price changes silently drop late usage. If a subscription item’s price changes during a billing cycle — a mid-cycle upgrade, for example — Stripe skips invoice recomputation at finalization, and any usage reported during the grace period appears on neither the current nor a subsequent invoice [6]. This affects both classic and flexible billing modes [6].
Stage 5: Invoicing and the grace period
Every Stripe invoice has a default finalization grace period of one hour, extendable to 72 hours [6]. During that window you can still report usage for the period that just closed, and Stripe updates the invoice to reflect the latest quantity [6].
Three constraints on this:
- The grace period applies only to invoices generated at the end of a subscription service period and to subscription schedule phase transitions that modify metered items. Threshold invoices reflect only usage accrued before the invoice was created [6].
- If an invoice contains line items matching rules with different grace periods, Stripe applies the more conservative one [6].
- The first invoice from a subscription set to charge automatically finalizes immediately, regardless of configured rules [6].
If your aggregation job runs slower than the grace period, usage lands in the next cycle. Set the grace period against your actual pipeline latency, not against a default.
Monitoring and spend controls
Alerts notify you when a customer crosses a usage threshold. Stripe’s use cases are instructive because they show that alerts are a product feature, not just an ops tool: email customers when they hit a self-configured limit, deprovision access past a free allowance, or notify sales when a self-serve account crosses into enterprise territory [7].
Constraints worth knowing before designing around them:
- Alerts are evaluated when you report usage after creating the alert, but the evaluation includes usage reported before it [7].
- Maximum 25 alerts per meter-and-customer combination [7].
- Billing thresholds don’t apply to trial subscriptions, and aren’t evaluated in the 24 hours before a subscription ends [7].
- Monetary thresholds must exceed the sum of any flat rates on usage-based subscription items [7].
- Invoiced amounts can slightly exceed thresholds, because invoices aren’t issued at the exact moment a threshold is crossed [7].
Stripe’s usage-alerting feature is marked public preview [7]. Treat it accordingly in any production dependency.
The hard parts nobody mentions
Multi-tenant attribution. When an organization has teams and projects, decide whether you bill the organization or the sub-unit. Both are valid; billing per-team requires per-team metering infrastructure, and billing at organization level makes internal allocation your customer’s problem.
Distributed counting. If your service runs on multiple instances, naive in-process counters under-count. You need either event sourcing with reconciliation, or a shared store with atomic increments.
Late and out-of-order events. Network partitions, retries, and offline processing all produce events that arrive after the fact. The 35-day acceptance window [2] tells you what the system tolerates; the grace period [6] tells you what actually gets billed. Those are different numbers, and the gap between them is unbilled revenue.
Silent ingestion failures. Stripe processes meter events asynchronously and surfaces problems through two events: v1.billing.meter.error_report_triggered for invalid usage events, and v1.billing.meter.no_meter_found for missing or invalid meter IDs [4]. Both use thin payloads, which require enabling Workbench to subscribe [4]. If you aren’t listening to these, usage can fail to record with no signal in your own systems.
Reference implementation: Stripe Meters
A meter event, created against a meter named hypernian_tokens [3][4]:
curl https://api.stripe.com/v1/billing/meter_events \ -u "sk_test_...:" \ -d event_name=hypernian_tokens \ -d "payload[value]=25" \ -d "payload[stripe_customer_id]={{CUSTOMER_ID}}" Canceling an incorrectly recorded event [3]:
curl https://api.stripe.com/v1/billing/meter_event_adjustments \ -u "sk_test_...:" \ -d type=cancel \ -d event_name=hypernian_tokens \ -d "cancel[identifier]={{METER_EVENT_IDENTIFIER}}" The payload keys are configurable. By default Stripe looks for stripe_customer_id and value, but you can remap them via customer_mapping and value_settings on the meter [2][3].
Where Stripe's basic tier stops
Stripe’s documentation is explicit that basic usage-based billing on the Meters API lacks several capabilities, listing them in a direct comparison with Metronome [5]:
Capability
Basic usage-based billing
Metronome
Prepaid credits and drawdown
Enterprise contracts, commits, minimums
Ramp schedules
Dimensional pricing
Real-time usage visibility
Multi-dimensional metering
High-volume event ingestion
The reverse also holds — Metronome does not support Connect, Adaptive Pricing, Workflows, or the Stripe Dashboard, and Checkout support requires custom API calls and webhook configuration [5].
Stripe’s guidance for existing Meters users is that migration is not required and basic usage-based billing remains fully supported [4][5].
What your metering system must guarantee
Whatever you build or buy, verify these six properties:
- Exactly-once semantics — duplicate deliveries resolve to one billable event, not two.
- Deterministic attribution — every event resolves to one billing entity, including after org membership changes mid-cycle.
- Bounded late-arrival handling — a documented rule for what happens to events that arrive after the period closes.
- Auditable correction — you can explain any invoice line item back to the underlying events.
- Configuration immutability awareness — you know which settings can never change, and versioned them accordingly.
- Failure visibility — rejected events produce an alert you actually receive.
Fact Check
Vendor capability and API claims on this page were verified against Stripe’s official documentation on 15 October 2026. Metering APIs change frequently — re-verify before implementing.
Verified against vendor documentation:
- Meter event fields, identifier uniqueness within a rolling 24-hour period, and the 35-day / 5-minute timestamp window — Stripe Meter Event API reference.
- Aggregation formulas (Sum, Count, Last), raw vs pre-aggregated ingestion, and meter configuration immutability — Stripe “Create and configure a meter.”
- Meter Event Adjustments limited to a 24-hour cancellation window and cannot alter finalized invoices — same source.
- Rate limits of 1,000 calls/second, one concurrent call per customer per meter, 10,000/sec via API v2 streams, 200,000/sec via sales — Stripe “Record usage for billing with the API.”
- Dimension cardinality limits (10,000 per meter per hour; 100 per customer per meter) and the
meter_event_dimension_count_too_higherror code — same. - Default 1-hour invoice finalization grace period, extendable to 72 hours, and its restriction to subscription cycle and phase-transition invoices — Stripe “Configure an invoice finalization grace period.”
- Mid-cycle price changes causing grace-period usage to be dropped — same.
- Alert limits (25 per meter-and-customer) and threshold constraints; feature marked public preview — Stripe “Monitor usage.”
- Capability comparison between basic usage-based billing and Metronome, including invoice-time credit reconciliation — Stripe “Compare basic usage-based billing and Metronome.”
- Stripe’s statement that Metronome is the recommended starting point for new integrations and that Meters is a lower-level primitive — Stripe “Basic usage-based billing” overview.
This page’s own analysis, not vendor claims:
- The five-stage pipeline framing, the “what your metering system must guarantee” checklist, and the “hard parts” section are our synthesis across vendor documentation, not Stripe terminology.
FAQ
What is the difference between a meter and a meter event?
A meter is configuration: it defines the event name, how events are ingested, and how they aggregate over a billing period. A meter event is a single record of usage sent to that meter. Meters attach to prices and form the basis of what’s billed [3].
Can I change a meter's aggregation method after launch?
No. After configuring a meter, the only changeable attribute is the display name [3]. Event name, ingestion mode, and aggregation formula are fixed.
How do I fix usage I recorded incorrectly?
Use a Meter Event Adjustment to cancel the event, but only if it was sent within the last 24 hours. If the usage already appears on a finalized invoice, it cannot be corrected through this mechanism [3].
What happens to usage reported after the billing period ends?
It depends on the invoice finalization grace period, which defaults to one hour and can extend to 72 [6]. Usage reported within the grace period is included in the invoice. Usage reported after finalization may appear in summaries but will not be added to any invoice [4].
Why does my usage data look correct in summaries but wrong on the invoice?
Two common causes. Stripe processes meter events asynchronously, so summaries and upcoming invoices may not immediately reflect recent events [4]. And if a subscription item’s price changed mid-cycle, Stripe skips invoice recomputation, dropping grace-period usage entirely [6].
Is the Usage Records API still usable?
Stripe now categorizes usage records documentation as legacy and directs new integrations to the Meters API or Metronome [4]. Existing integrations remain supported, but new work should not start there.
How many events per second can I send?
1,000 per second per account on the standard endpoint, with one concurrent call per customer per meter. API v2 meter event streams raise this to 10,000 per second, and Stripe offers up to 200,000 per second through sales [4].
Sources
- Stripe — Basic usage-based billing overview — https://docs.stripe.com/billing/subscriptions/usage-based
- Stripe — The Meter Event object — https://docs.stripe.com/api/billing/meter-event/object
- Stripe — Create and configure a meter — https://docs.stripe.com/billing/subscriptions/usage-based/meters/configure
- Stripe — Record usage for billing with the API — https://docs.stripe.com/billing/subscriptions/usage-based/recording-usage-api
- Stripe — Compare basic usage-based billing and Metronome — https://docs.stripe.com/billing/subscriptions/usage-based/compare-metronome
- Stripe — Configure an invoice finalization grace period — https://docs.stripe.com/billing/subscriptions/usage-based/configure-grace-period
- Stripe — Monitor usage with alerts — https://docs.stripe.com/billing/subscriptions/usage-based/monitor
- Stripe — How usage-based billing works — https://docs.stripe.com/billing/subscriptions/usage-based/how-it-works
All sources accessed 15 October 2026.