Data as of Sep 19, 2026 · Based on 404 AI responses from ChatGPT Search and Google AI Mode · See how Parse measures this
If you need high-volume, real-time enterprise metering, pick Metronome. If you run API/infrastructure products, pick
Orb for flexible, developer-focused metering. Use
Lago for self-hosted control and no revenue share. Choose Vayu when finance needs to own pricing without heavy engineering. is a strong all-in-one for growing companies combining subscriptions and usage.
Brands AI recommends here
Named in 65% of answers
Best for high-volume enterprise or Stripe-native businesses that need real-time conversion of usage into billable events; evidence shows Metronome handles large-scale, real-time metering, but it can create vendor lock-in with Stripe.
Named in 54% of answers
Named in 51% of answers
Named in 47% of answers
Best when you want an open-source, self-hosted billing stack with no revenue-share and full control; evidence shows Lago excels at flexible, high-speed usage calculations, but you must operate and maintain the infrastructure yourself.
A usage-based billing engine with complex tiers is best designed as a **pricing/rating platform**, not as invoice code. Separate the system into metering, aggregation, rating, and invoicing so pricing changes do not require application rewrites. [Let's Build…
A usage-based billing engine with complex tiers is best designed as a pricing/rating platform, not as invoice code. Separate the system into metering, aggregation, rating, and invoicing so pricing changes do not require application rewrites.
A reference architecture:
┌─────────────────┐
Product Events ─► Usage Ingestion │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Meter Store │
│ (raw events) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Aggregator │
│ usage/month/etc │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Rating Engine │
│ tiers, credits, │
│ discounts │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Invoice Engine │
│ line items/tax │
└─────────────────┘
Capture immutable usage events:
{
"event_id": "evt_123",
"customer_id": "cust_456",
"metric": "api_calls",
"quantity": 1,
"timestamp": "2026-09-19T04:00:00Z",
"dimensions": {
"region": "us-east",
"model": "premium"
}
}
Requirements:
A billing system should treat usage events as financial records, not disposable analytics data.
Do not hardcode tiers. Store pricing as configuration.
Example:
{
"plan": "enterprise",
"metric": "api_calls",
"billing_period": "monthly",
"tiers": [
{
"from": 0,
"to": 10000,
"price_per_unit": 0.01
},
{
"from": 10001,
"to": 1000000,
"price_per_unit": 0.005
},
{
"from": 1000001,
"to": null,
"price_per_unit": 0.002
}
]
}
This lets pricing teams modify rates without deployments.
The rating engine converts usage into money.
Support multiple strategies:
Example:
Calculation:
def graduated_price(quantity, tiers):
remaining = quantity
total = 0
for tier in tiers:
available = tier.limit - tier.start if tier.limit else remaining
used = min(remaining, available)
total += used * tier.price
remaining -= used
if remaining <= 0:
break
return total
Different from graduated tiers:
Example:
Plan:
$500/month
Includes 100,000 API calls
Usage:
150,000 calls
Bill:
$500 base
50,000 overage × $0.004
Example:
Annual commitment:
10M API calls
Actual usage:
12M API calls
Charge:
Committed block + 2M overage
A minimal relational design:
customers
----------
id
account_id
currency
meters
----------
id
name
aggregation_type
Examples:
COUNT
SUM
MAX
UNIQUE_COUNT
plans
----------
id
version
effective_from
effective_to
price_rules
----------
plan_id
metric_id
tier_start
tier_end
unit_price
pricing_strategy
usage_events
----------
id
customer_id
metric_id
quantity
occurred_at
idempotency_key
charges
----------
customer_id
billing_period
metric
quantity
amount
pricing_rule_version
Keeping the pricing version attached to charges prevents historical invoices from changing when prices change.
Generate invoices from rated line items:
Invoice #10001
Base subscription:
Enterprise plan $500.00
API usage:
0-10k calls $100.00
10k-1M calls $450.00
1M+ calls $80.00
Credits:
Annual commitment -$200.00
Total:
$930.00
Never calculate invoices directly from raw events during checkout/billing close. Use a reproducible rating step.
Usage visibility and alerts are especially important because unexpected consumption charges can create customer disputes.
Build your own if you need:
Consider an existing billing platform if you need:
A common hybrid approach is:
A production-grade implementation would typically start with:
The most important design choice is making the rating engine declarative and versioned rather than embedding pricing rules in application code.
When dealing with usage-based pricing and complex tiers (tiered pricing, volume pricing, graduated tiers, or prepaid credit drawdowns), traditional payment gateways like standard Stripe Billing often require building brittle custom workarounds. To handle high-throughput metering and complex, multi-dimensional rating…
When dealing with usage-based pricing and complex tiers (tiered pricing, volume pricing, graduated tiers, or prepaid credit drawdowns), traditional payment gateways like standard Stripe Billing often require building brittle custom workarounds.
To handle high-throughput metering and complex, multi-dimensional rating logic out of the box, specialized billing engines fall into three primary categories:
To help narrow down the right engine for your architecture, could you share:
Yes. For **usage-based pricing with complex tiers**, I’d build the billing engine around an immutable usage ledger plus a versioned pricing engine—not around invoices themselves. A useful architecture is: ```
Yes. For usage-based pricing with complex tiers, I’d build the billing engine around an immutable usage ledger plus a versioned pricing engine—not around invoices themselves.
A useful architecture is:
┌──────────────────┐
Usage events ──────►│ Usage ingestion │
└────────┬─────────┘
│
dedupe/idempotency
│
▼
┌──────────────────┐
│ Usage ledger │
│ immutable │
└────────┬─────────┘
│
aggregation/windowing
│
▼
┌──────────────────┐
│ Pricing engine │
│ versioned rules │
└────────┬─────────┘
│
priced line items
│
▼
┌──────────────────┐
│ Invoice engine │
└────────┬─────────┘
│
▼
Payments / GL / ERP
Every event should have something like:
event_id
customer_id
metric
quantity
timestamp
dimensions
source
event_id needs to be idempotent so retries don't double-bill customers. Keep the raw event permanently; derive aggregates from it rather than modifying the original record.
This mirrors the basic metering lifecycle used by modern billing systems: ingest usage, aggregate it over a billing period, apply pricing, then invoice.
Don't encode pricing logic directly into subscription/invoice code.
For example:
{
"metric": "api_requests",
"model": "graduated",
"tiers": [
{ "up_to": 10000, "unit_price": 0.002 },
{ "up_to": 100000, "unit_price": 0.001 },
{ "up_to": null, "unit_price": 0.0005 }
]
}
Then support multiple pricing models:
$100/month$0.01/request$50 per 10,000 unitsThe distinction between graduated and volume pricing is particularly important: graduated pricing applies each tier's price only to the usage falling within that tier, whereas volume pricing applies the selected tier's price to the entire quantity.
This is critical.
Never mutate:
Plan A = $0.001/request
into:
Plan A = $0.002/request
Instead:
pricing_version 17
effective_from: 2026-01-01
effective_to: 2026-06-30
pricing_version 23
effective_from: 2026-07-01
An invoice should always reference the exact pricing version used to calculate it.
That gives you reproducibility: six months later, you can explain exactly why an invoice was $13,842.17.
Don't have:
calculatePrice(usage) => 1384217
Return something auditable:
{
total: 1384217,
currency: "USD",
lines: [
{
metric: "api_requests",
tier: 1,
quantity: 10000,
unitPrice: 0.002,
subtotal: 2000
},
{
metric: "api_requests",
tier: 2,
quantity: 90000,
unitPrice: 0.001,
subtotal: 9000
},
{
metric: "api_requests",
tier: 3,
quantity: 684217,
unitPrice: 0.0005,
subtotal: 342.1085
}
]
}
Then round according to an explicit currency/rounding policy.
This makes customer support, invoice reconciliation, and financial audits dramatically easier.
This is probably the most important architectural decision.
Metering answers:
How much did the customer consume? Pricing answers:
What should that consumption cost? For example:
Customer A
├── API requests: 1,250,000
├── GPU seconds: 83,400
└── Storage GB-hours: 42,812
The pricing engine can then apply completely different rules to each metric.
That also means you can change pricing without changing your product's telemetry pipeline.
I'd make the lifecycle:
Raw usage
↓
Normalized usage
↓
Aggregated usage
↓
Rated usage
↓
Invoice lines
↓
Invoice
For example:
1,250,000 API requests
↓
pricing version 42
↓
10,000 × $0.002
90,000 × $0.001
1,150,000 × $0.0005
↓
$685.00
The rated usage record becomes the bridge between your pricing engine and accounting system.
Usage systems inevitably receive:
Don't overwrite historical records.
Use compensating entries:
+1000 API calls
-1000 API calls
+1200 corrected API calls
Then rerate the affected billing period.
I'd start with these entities:
Customer
Subscription
SubscriptionItem
Metric
UsageEvent
UsageAggregate
PricingPlan
PricingVersion
PricingRule
RatingResult
Invoice
InvoiceLine
Credit
Adjustment
And keep the boundaries clean:
UsageEvent
↓
Meter
↓
UsageAggregate
↓
PricingVersion + PricingRules
↓
RatingResult
↓
InvoiceLine
↓
Invoice
Use integer minor units or a decimal type:
$12.34 → 1234 cents
For very small usage prices, you may also need decimal quantities/prices with substantially more precision before the final currency rounding.
If your tiers are genuinely complex, I'd give pricing its own declarative representation:
metric: inference_tokens
billing_period: monthly
pricing:
- when:
model: standard
tiers:
- up_to: 1000000
price: 0.000002
- up_to: 10000000
price: 0.0000015
- up_to: null
price: 0.000001
- when:
model: premium
tiers:
- up_to: 1000000
price: 0.000008
- up_to: null
price: 0.000006
Then your engine becomes a deterministic interpreter for this pricing configuration.
That's much easier to test than hundreds of nested if statements.
For a production system, I'd aim for:
Event ingestion → immutable usage ledger → aggregation → versioned pricing DSL → deterministic rating engine → invoice lines → payment provider/accounting
And I'd make the rating engine a pure function wherever possible:
rating(
usage,
pricing_version,
customer_context,
billing_period
) → rating_result
That gives you an especially valuable property: the exact same inputs always produce the exact same bill.
Stripe's own usage-based model similarly separates meters/usage events from prices and billing, and supports both graduated and volume tiering.
If you're building this yourself, I can next lay out a production-ready database schema + TypeScript pricing engine, including graduated/volume tiers, credits, minimums, commitments, proration, idempotency, and invoice generation.
Use integer minor units or a decimal type:
$12.34 → 1234 cents
For very small usage prices, you may also need decimal quantities/prices with substantially more precision before the final currency rounding.
If your tiers are genuinely complex, I'd give pricing its own declarative representation:
When your pricing model moves beyond simple flat fees into complex, multi-tiered, or high-throughput usage data (like AI tokens, API calls, or compute hours), standard payment processor billing modules (like basic Stripe Billing) often hit…
When your pricing model moves beyond simple flat fees into complex, multi-tiered, or high-throughput usage data (like AI tokens, API calls, or compute hours), standard payment processor billing modules (like basic Stripe Billing) often hit walls.
The top-tier specialized usage-based billing engines available depend on whether you prefer a developer-first API, an open-source self-hosted stack, or enterprise-grade contract flexibility:
To help narrow down the best fit, tell me:
When your pricing moves past flat-rate tiers into metered, multi-attribute, or volume-tiered consumption (e.g., sliding-scale API calls, sliding compute units, or tiered overages), standard checkout tools like basic Stripe Billing can become brittle and require heavy custom…
When your pricing moves past flat-rate tiers into metered, multi-attribute, or volume-tiered consumption (e.g., sliding-scale API calls, sliding compute units, or tiered overages), standard checkout tools like basic Stripe Billing can become brittle and require heavy custom engineering.
A purpose-built usage-based billing engine handles event ingestion, aggregation, complex pricing calculations (graduated or volume tiers), and invoicing, then syncs with a payment processor to charge the card.
The leading usage-based billing engines optimized for complex tiers are categorized below by their strengths:
To help narrow down which engine fits your architecture best, let me know:
Yes. For **complex usage-based pricing**, I’d avoid putting pricing logic directly into application code. Treat billing as a small domain-specific engine with immutable pricing versions, metering, rating, and invoicing as separate stages. A good architecture looks like: ```
Yes. For complex usage-based pricing, I’d avoid putting pricing logic directly into application code. Treat billing as a small domain-specific engine with immutable pricing versions, metering, rating, and invoicing as separate stages.
A good architecture looks like:
Usage Events
│
▼
┌─────────────┐
│ Metering │ aggregate usage by customer / feature / period
└──────┬──────┘
▼
┌────────────────┐
│ Pricing Catalog │ versioned plans, tiers, discounts, commitments
└───────┬────────┘
▼
┌──────────────┐
│ Rating Engine │ convert usage → monetary charges
└──────┬───────┘
▼
┌────────────┐
│ Invoice Run │ consolidate charges, tax, credits
└──────┬─────┘
▼
Invoice / Ledger
Represent a price as data, not code.
For example:
{
"price_id": "api_requests_v4",
"currency": "USD",
"billing_period": "month",
"model": "graduated",
"tiers": [
{ "up_to": 10000, "unit_price": 0.01 },
{ "up_to": 100000, "unit_price": 0.008 },
{ "up_to": null, "unit_price": 0.005 }
]
}
Then your rating engine can support multiple models:
$99/month$0.01 × usage$20, rounded upGraduated and volume pricing are importantly different: with 6,000 units and tiers of $0.30, $0.20, $0.10, graduated pricing charges each tier separately, while volume pricing charges all 6,000 at the highest achieved tier.
This is probably the most important architectural decision.
Don't do:
customer → "Pro plan"
Do:
customer
↓
subscription
↓
plan_version_7
↓
price_version_12
When you change a price, create a new version. Existing subscriptions continue using the old version unless explicitly migrated. This also makes historical invoices reproducible. Versioned plans and subscriptions bound to specific versions are a pattern used by OpenMeter.
Store immutable usage events such as:
{
"event_id": "evt_123",
"customer_id": "cus_42",
"meter": "ai_tokens",
"timestamp": "2026-09-10T18:22:31Z",
"quantity": 1842,
"dimensions": {
"model": "gpt-x",
"region": "us-east"
}
}
Then derive meter totals from those events.
That gives you idempotency and auditability. If the pricing configuration changes or you discover a metering bug, you can recalculate the rating from the underlying events rather than trying to reconstruct what happened from an invoice.
I'd make the core API something like:
rate({
price,
usage,
period,
customer,
credits
}) => {
subtotal,
discounts,
commitments,
taxes,
total,
lineItems
}
For example:
const result = rate({
price: apiPrice,
usage: 125_000,
period: {
start: "2026-09-01",
end: "2026-10-01"
}
});
And return detailed lines:
{
"subtotal": 920.00,
"line_items": [
{
"tier": 1,
"quantity": 10000,
"unit_price": 0.01,
"amount": 100.00
},
{
"tier": 2,
"quantity": 90000,
"unit_price": 0.008,
"amount": 720.00
},
{
"tier": 3,
"quantity": 25000,
"unit_price": 0.004,
"amount": 100.00
}
]
}
Detailed billing lines are valuable both for debugging and for giving customers an understandable invoice.
Keep the calculation pipeline explicit:
raw usage
↓
included usage / usage credits
↓
tier calculation
↓
base charge
↓
percentage discounts
↓
minimum / maximum commitment
↓
tax
↓
final amount
For example, a usage discount should reduce billable quantity before the tier calculation, while percentage discounts happen afterward. This ordering matters enormously once pricing gets complicated.
Customer
Subscription
Plan
PlanVersion
PlanPhase
Feature
Meter
Price
Tier
Discount
Commitment
UsageEvent
UsageAggregate
RatingRun
Charge
Invoice
InvoiceLine
Credit
Payment
The important relationships are:
PlanVersion
├── PlanPhase
│ └── Price
│ └── Tier[]
└── Entitlement[]
Subscription
└── PlanVersion
UsageEvent
└── Meter
Meter + Subscription + Price
└── RatingRun
└── Charge[]
└── InvoiceLine
This is close to the conceptual separation used by modern usage-billing systems: features/meters, versioned plans, rate cards/prices, subscriptions, and invoices.
If you're building a SaaS product with serious pricing complexity, I'd evaluate an existing metering/billing system before implementing the entire engine yourself.
OpenMeter is particularly relevant because it supports graduated and volume tiers, packages, overages, discounts, commitments, entitlements, plan versioning, and invoicing.
Stripe is another option if you want payments and billing infrastructure tightly integrated; its current Billing offering includes usage-based billing capabilities, with more advanced usage pricing available through Metronome.
If you're building this yourself, I would start with a pure, deterministic RatingEngine plus versioned JSON pricing definitions. That gives you the flexibility to add increasingly exotic pricing rules without turning your application into a giant collection of if/else statements.
You need a specialized metering and billing platform like `Orb or Metronome` for complex, high-throughput usage-based pricing, or Chargebee if you also require traditional subscription management.[](https://www.stigg.io/blog-posts/usage-based-billing-software)…
You need a specialized metering and billing platform like Orb or Metronome for complex, high-throughput usage-based pricing, or Chargebee if you also require traditional subscription management.
Modern usage-based billing engines handle high-volume event ingestion, complex tier calculations (volume, tiered, stair-step, or graduated pricing), and hybrid models.
Top Usage-Based Billing Engines
| Engine | Best For | Key Strengths |
|---|---|---|
| Orb | Complex B2B & AI/Cloud pricing | SQL-defined metrics, real-time event processing, flexible packaging |
| Metronome | High-scale usage & Stripe ecosystems | Robust API mediation, enterprise contract management, reliable metering |
| Lago | Open-source flexibility | Self-hosted or cloud options, transparent data ownership, no revenue share |
| Chargebee | Hybrid subscription + consumption | CPQ integration, invoicing, tax compliance, dunning management |
Key Capabilities to Evaluate
To help narrow down the ideal choice, tell me:
Yes. For **usage-based pricing with complex tiers**, I’d avoid building the rating logic from scratch unless billing itself is a core product capability. ### Strong options - **Metronome** — probably the strongest fit if you need sophisticated rate cards, multidimensional pricing, hybrid subscriptions, credits,…
Yes. For usage-based pricing with complex tiers, I’d avoid building the rating logic from scratch unless billing itself is a core product capability.
I'd structure it as separate layers:
Usage Events
↓
Metering / Aggregation
↓
Rating Engine
↓
Pricing Rules / Tiers
↓
Credits / Commitments / Discounts
↓
Invoice Lines
↓
Invoice + Payment
The rating engine should be deterministic and versioned. For example:
Plan: Pro
0–10,000 units $0.010 / unit
10,001–100,000 $0.008 / unit
100,001–1,000,000 $0.005 / unit
1,000,001+ $0.003 / unit
Minimum monthly charge: $500
Included allowance: 2,000 units
Overage: graduated
Discount: 15% enterprise
But I'd make the pricing model data-driven rather than encoding those rules in application code:
{
"model": "graduated",
"dimension": "api_calls",
"tiers": [
{ "up_to": 10000, "unit_price": 0.010 },
{ "up_to": 100000, "unit_price": 0.008 },
{ "up_to": 1000000, "unit_price": 0.005 },
{ "up_to": null, "unit_price": 0.003 }
]
}
Crucially, support both graduated and volume tiers. A graduated model charges each slice at its tier's rate; a volume model applies the customer's final tier rate to all units. Confusing those two is a classic billing bug.
I'd also make these first-class features:
My recommendation: if you tell me your actual pricing rules—e.g. “$X/month includes 100k API calls, then graduated tiers, plus different rates based on region/model, with annual commits and credits”—I can design the billing engine architecture, database schema, pricing DSL, and calculation algorithm around them.
Plan: Pro
0–10,000 units $0.010 / unit
10,001–100,000 $0.008 / unit
100,001–1,000,000 $0.005 / unit
1,000,001+ $0.003 / unit
Minimum monthly charge: $500
Included allowance: 2,000 units
Overage: graduated
Discount: 15% enterprise
But I'd make the pricing model data-driven rather than encoding those rules in application code:
{
"model": "graduated",
"dimension": "api_calls",
"tiers": [
{ "up_to": 10000, "unit_price": 0.010 },
{ "up_to": 100000, "unit_price": 0.008 },
{ "up_to": 1000000, "unit_price": 0.005 },
{ "up_to": null, "unit_price": 0.003 }
]
}
Crucially, support both graduated and volume tiers. A graduated model charges each slice at its tier's rate; a volume model applies the customer's final tier rate to all units. Confusing those two is a classic billing bug.
I'd also make these first-class features:
My recommendation: if you tell me your actual pricing rules—e.g. “$X/month includes 100k API calls, then graduated tiers, plus different rates based on region/model, with annual commits and credits”—I can design the billing engine architecture, database schema, pricing DSL, and calculation algorithm around them.
Handling usage-based pricing with complex tiers (graduated tiers, volume pricing, matrix/multi-dimensional pricing, minimum commitments, or prepaid credits) requires a dedicated usage-first billing engine rather than a traditional flat-rate subscription…
Handling usage-based pricing with complex tiers (graduated tiers, volume pricing, matrix/multi-dimensional pricing, minimum commitments, or prepaid credits) requires a dedicated usage-first billing engine rather than a traditional flat-rate subscription tool.
The top billing engines that specialize in complex consumption and tiered models break down by use-case and architecture:
To help narrow down the ideal engine, tell me:
Yes. For **usage-based pricing with complex tiers**, I’d avoid building the entire billing stack from scratch unless billing itself is a core product differentiator. ### Strong options - **[metronome.com](https://metronome.com/?utm_source=chatgpt.com)** — My first choice for sophisticated enterprise usage billing. It…
Yes. For usage-based pricing with complex tiers, I’d avoid building the entire billing stack from scratch unless billing itself is a core product differentiator.
Your billing engine should separate metering, rating, and invoicing:
Usage Events
│
▼
┌──────────────┐
│ Metering │ aggregate usage
└──────┬───────┘
▼
┌──────────────┐
│ Pricing/Rater│ apply tiers, dimensions,
│ │ discounts, credits, etc.
└──────┬───────┘
▼
┌──────────────┐
│ Charges │ immutable rated line items
└──────┬───────┘
▼
┌──────────────┐
│ Invoice │
└──────────────┘
The key is making the pricing model declarative, rather than embedding pricing rules throughout application code.
For example:
metric: api_calls
aggregation: sum
tiers:
- up_to: 10000
price: 0.01
- up_to: 100000
price: 0.008
- above: 100000
price: 0.005
dimensions:
- region
- api_type
discounts:
- customer_segment: enterprise
percent: 15
I'd also make the engine support graduated tiers vs. volume tiers explicitly, because they produce very different bills. Add versioned price books, effective dates, idempotent usage events, corrections/re-rating, prepaid credits, minimum commitments, caps, and a full audit trail from raw event → meter → rate → invoice.
If you tell me your exact pricing model (e.g. “first 1M API calls at $X, next 9M at $Y, plus a monthly minimum, with different rates by region”), I can design the billing-engine architecture and data model around it.