Stripe Usage Records Migration: Move to Billing Meters (Basil)

Migrate Stripe legacy Usage Records to Billing Meters before upgrading to 2025-03-31.basil. Inventory UsageRecord, aggregate_usage, action=set and billing_threshold dependencies, with a free migration checker.

8 min read

stripeusage recordsbilling metersmigrationusage metering
Check your integration: use the free Stripe Usage Records migration checker to inventory the legacy resources and semantics you still depend on.

TL;DR: Stripe removed the legacy Usage Record resources from API version 2025-03-31.basil. During migration, Stripe tells legacy integrations to keep reporting Usage Records on 2025-02-24.acacia or earlier while they also begin sending Billing Meter events. This is not just a URL rename: meters are customer/event based, support different aggregation and ingestion modes, and legacy fields such as aggregate_usage and billing_thresholds were removed from the Basil contract.

This is the migration most teams discover by trying to upgrade their Stripe SDK and finding that a resource they depend on no longer exists.

What was removed, exactly

In API version 2025-03-31.basil, Stripe removed:

  • UsageRecord and UsageRecordSummary, and their endpoints
  • aggregate_usage on prices
  • billing_thresholds

Billing meters are the replacement, and Stripe is explicit that they are now the only solution for usage-based billing. There is no parallel track being maintained.

The old API version is migration debt, not an outage

Stripe's migration guide explicitly allows legacy Usage Records to keep running while you adopt Billing Meters, but those calls must use 2025-02-24.acacia or earlier because Basil removes the old resources. That makes version pinning a legitimate migration bridge.

The important constraint is narrower than "all new Stripe features disappear": the production paths that still depend on removed legacy resources prevent you from moving those API/webhook integrations cleanly onto the Basil contract. The longer those call sites remain, the more upgrade and test work accumulates around them.

Use the pin to create a controlled dual-reporting window, not as the final architecture.

The part that is not a URL swap

This is where the migration bites, and it is skipped in most write-ups because it only shows up once you look at your own call sites.

Usage records (old)Meter events (new)
Keyed on Subscription item Customer, plus a meter event name
Needs a subscription first Yes — no subscription item, nowhere to report No. You can collect usage before the subscription exists
Authoritative / pre-aggregated values action: 'set' with legacy last-style aggregation No 1:1 field rename. Current meters support last aggregation and raw or hourly/daily pre-aggregated ingestion; choose semantics deliberately.
Deduplication Effectively your problem identifier on the event
Late arrivals Legacy rules depend on aggregation mode and billing period Invoice finalization has a 1-hour default grace period that can be configured up to 72 hours

If you used action: 'increment'

You are in the easy case. Increment maps onto meter events almost directly: each report becomes an event with a value, and the meter sums them. The work is plumbing — resolve the Stripe customer instead of the subscription item, name your meters, and start sending an identifier.

If you used action: 'set'

Stop before converting each authoritative total into an additive meter event. The current Billing Meter model has more options than the first meter release: aggregation formulas include sum, count, and last, while event ingestion can be raw or pre-aggregated into hourly/daily windows.

That means set is a semantics review, not automatically a rewrite to deltas. Ask what the old total represented:

  • A true last-known gauge: investigate a meter configured with last.
  • An hourly/daily authoritative bucket: investigate pre-aggregated ingestion, where a newer value replaces the earlier value inside that time window.
  • A cumulative month-to-date counter: you may still need to emit deltas or transform the counter before reporting it, because repeatedly sending a growing total into a summed meter would overcount.

Stripe's own migration guide also calls out one legacy aggregation it does not support in Billing Meters: max. Inventory the old aggregate_usage value rather than assuming every legacy Price has the same migration shape.

The grace period is billing configuration, not a fixed constant

Stripe currently defaults invoice finalization to a one-hour grace period, during which usage for the previous billing period can still be reported. That default is configurable: Stripe documents finalization delays up to 72 hours.

So do not encode "one hour" into your transport design as if it were a protocol guarantee. Read the account's invoice-finalization configuration, size your queue/reconciliation policy around it, and remember that the first automatically collected subscription invoice finalizes immediately rather than following those normal delay rules.

This is the same question every metering system has to answer, and it is worth reading the general version of it before you decide.

A migration order that does not risk revenue

  1. Inventory your call sites and actions. Specifically: how many use set. That number decides whether this is a week or a quarter.
  2. Create meters and prices alongside the old ones. Do not modify live prices; make new ones.
  3. Dual-report. Send usage records and meter events for a full billing period. Stripe's own guidance is to keep sending usage records until the migration is complete — take that literally.
  4. Reconcile per customer, per meter, per period. Matching grand totals is not agreement. Check each key, and expect the discrepancies to cluster around retries and period boundaries.
  5. Plan the subscription cutover deliberately. Stripe's migration guide uses subscription schedules to move subscriptions to the new meter-backed price at the end of the current phase.
  6. Bump the API version last, once nothing calls the old resources.
  7. Keep the old data readable for at least one dispute cycle. The first argument about a number will happen after you have cut over.

The question worth asking while you are in here

You are about to re-instrument every usage call site in your product. That is the expensive part, and it is the part you would have to repeat if you ever changed billing vendor — which, after Stripe bought Metronome, Adyen bought Orb and Salesforce bought m3ter, is no longer a hypothetical.

So it is a reasonable moment to ask whether product code should post its only copy of usage directly into the payment processor, or whether an independent metering layer should preserve the quantity first and let Stripe remain the pricing/invoice system. UsageBox does not rate Stripe prices or rewrite subscriptions; the value of that boundary is that your product's measurement contract and raw usage evidence do not have to move at the same time as the biller.

Related reading

Key Topics

  • •stripe
  • •usage records
  • •billing meters
  • •migration
  • •usage metering

Related Articles

Explore more articles on similar topics to deepen your understanding of usage-based billing.

Stripe Billing Alternatives for Usage-Based Billing in 2026

Most teams looking for a Stripe Billing alternative have a metering problem, not a Stripe problem — and Stripe's own ans...

8 min readRead more

Designing Billing Meters: Value Types, Units, and the Four Aggregations That Decide the Invoice

A billing meter is a small schema decision with invoice-sized consequences: value type, aggregation (sum, count, max, un...

8 min readRead more

ChatGPT Plus in Other Apps: Supported Apps & Limits (2026)

Which apps can actually use your ChatGPT Plus plan? Verified OpenAI partner list, sign-in-only exceptions, coming-soon s...

15 min readRead more

Explore More Articles

Discover our complete collection of usage-based billing guides and implementation patterns.

View all articles