Data as of Aug 25, 2026 · Based on 378 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
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.
Best for API-driven products and engineering teams needing flexible credits, prepaid and graduated tiers; evidence shows Orb is developer-led and API-first, but it requires engineering investment compared with finance-facing tools.
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.
Best when finance teams need to own pricing and auditing without heavy engineering; evidence shows Vayu focuses on finance control and auditability, though it’s less engineering-centric than API-first metering tools.
Yes. For complex usage-based pricing, I’d build the billing engine as a deterministic pipeline rather than putting pricing logic directly into your application.
A good architecture is:
Usage Events
│
▼
┌──────────────┐
│ Ingestion │ validate, authenticate, deduplicate
└──────┬───────┘
▼
┌──────────────┐
│ Metering │ sum/count/max/last, dimensions
└──────┬───────┘
▼
┌──────────────┐
│ Aggregation │ customer + metric + billing period
└──────┬───────┘
▼
┌──────────────┐
│ Rating Engine│ tiers, volume, discounts, minimums,
│ │ commitments, credits, overages
└──────┬───────┘
▼
┌──────────────┐
│ Invoice │ immutable line-item calculation
└──────┬───────┘
▼
Payments / ERP / Revenue Recognition
This separation is important: modern usage-billing systems similarly distinguish metering/aggregation from the pricing configuration and invoice calculation.
Make pricing data-driven, not hardcoded:
type PricingPlan = {
id: string;
currency: string;
billingPeriod: "monthly" | "annual";
components: PricingComponent[];
};
type PricingComponent = {
metric: string;
baseFee?: Money;
includedUnits?: number;
tiers?: Tier[];
mode: "graduated" | "volume" | "flat";
};
type Tier = {
upTo: bigint | null;
unitPrice: Money;
flatFee?: Money;
};
For example:
{
"metric": "api_requests",
"baseFee": 4900,
"includedUnits": 10000,
"mode": "graduated",
"tiers": [
{ "upTo": 10000, "unitPrice": 0 },
{ "upTo": 100000, "unitPrice": 2 },
{ "upTo": 1000000, "unitPrice": 1 },
{ "upTo": null, "unitPrice": 0.5 }
]
}
The engine should distinguish graduated tiers from volume tiers. With graduated pricing, each portion of usage gets its tier's price; with volume pricing, the achieved tier's price can apply to the entire quantity. That distinction is fundamental to getting invoices right.
Keep the core rating function pure:
function rateUsage(
usage: bigint,
pricing: PricingPlan
): InvoiceLine[] {
// no database calls
// no network calls
// deterministic
}
For graduated tiers:
usage = 250,000
first 10,000 × $0.00
next 90,000 × $0.002
next 150,000 × $0.001
subtotal = $330
Every calculation should return a breakdown, not just a total:
{
"usage": 250000,
"currency": "USD",
"total": 33000,
"lines": [
{
"tier": 1,
"quantity": 10000,
"unitPrice": 0,
"amount": 0
},
{
"tier": 2,
"quantity": 90000,
"unitPrice": 2,
"amount": 18000
},
{
"tier": 3,
"quantity": 150000,
"unitPrice": 1,
"amount": 15000
}
]
}
That breakdown is extremely valuable for customer-facing invoices, debugging, disputes, and finance reconciliation.
I'd make these first-class concepts rather than special cases buried in code:
Dimensions are particularly useful when pricing depends on attributes such as model, token type, region, or event type.
Give every usage event a globally unique ID:
{
"eventId": "evt_01J...",
"customerId": "cus_123",
"metric": "api_requests",
"quantity": 37,
"timestamp": "2026-08-30T03:14:00Z",
"dimensions": {
"region": "us-east",
"model": "pro"
}
}
Then enforce:
eventId → exactly one accepted usage event
You want idempotent ingestion, because retries are inevitable. A billing engine that occasionally double-counts an API request is much worse than one that's slightly slower.
One of the most important design decisions:
Never calculate an invoice from today's pricing configuration. Calculate it from the pricing version that was effective when the usage occurred. Store something like:
pricing_plan_id
pricing_version
effective_from
effective_to
Then an invoice records:
Invoice
├── billing_period
├── pricing_version
├── usage_snapshot
├── rating_result
└── line_items
This lets you answer:
"Why was this customer charged $1,842.73?" months later, even if the pricing catalog has changed.
For a serious production system:
┌───────────────┐
│ Pricing Admin │
└───────┬───────┘
│
Pricing DB
│
▼
Usage → Ingestion → Metering → Rating → Invoicing
│ │ │ │
▼ ▼ ▼ ▼
Event DB Usage DB Price DB Invoice DB
I'd also make the rating engine a standalone library/service with no side effects. That makes it possible to run:
actual invoice
│
├── rating engine
│
└── expected invoice
and compare the result before finalizing the bill.
That's particularly useful for a preview invoice and for regression-testing pricing changes. Stripe's own usage-billing architecture likewise separates usage ingestion, meters, prices, billing, and monitoring.
If your requirements are genuinely unusual—multiple dimensions, negotiated contracts, commitments, complex tier combinations, credits, and custom formulas—I would own the metering/rating model and potentially delegate payment collection to something like stripe.com. Stripe supports metered usage and tiered pricing, but your exact pricing semantics may still warrant a dedicated rating layer.
If you tell me your pricing rules (for example, "$0.01 per API call, first 100k free, then graduated tiers, with annual commitments and customer-specific discounts"), I can design the database schema + pricing DSL + rating algorithm + API for the engine.
When building or adopting a billing engine for complex, usage-based tiers (tiered, graduated, volume-based, or commitment-plus-overage models), modern architecture typically splits into developer-first/usage-native systems versus traditional subscription platforms with usage add-ons.
The top billing engines capable of handling complex tiering and high-throughput event metering fall into distinct categories:
To help narrow down the right engine, tell me:
If you mean a buy-vs-build billing engine, I’d shortlist these:
If your pricing looks like:
$0.01 per API call for the first 1M → $0.008 for the next 9M → $0.005 thereafter, plus a monthly minimum, customer-specific discounts, prepaid credits, multiple usage dimensions, annual commits, and mid-cycle plan changes I'd lean Metronome or Orb, rather than trying to implement the rating logic yourself.
The key distinction is metering vs. rating. A meter answers “how much did the customer consume?”; the rating engine answers “given this usage, contract, tier structure, discounts, credits, and billing period, exactly how much do they owe?” Stripe's meter architecture explicitly separates usage aggregation from pricing.
If you're building the engine yourself, I can also lay out a production architecture—event ingestion → usage aggregation → pricing/rating engine → invoice ledger—with a data model and algorithm for arbitrary tier rules.
Choosing a usage-based billing engine with complex tiering (such as graduated, volume-based, or tiered with minimum commitments) depends heavily on whether you need a developer-first metering layer or a complete financial operations/quote-to-cash suite.
Top-tier solutions categorize by architectural fit and pricing complexity:
To help narrow down the ideal engine, tell me:
If you need complex usage-based pricing rather than simple subscription billing, I’d shortlist these:
A good engine should model something like:
Usage events
↓
Billable metric
↓
Pricing dimensions
├── customer
├── product
├── region
├── usage type
└── contract
↓
Rating engine
├── graduated tiers
├── volume tiers
├── minimums / maximums
├── credits
├── discounts
├── commitments
└── custom overrides
↓
Invoice line items
↓
Payment / ERP / revenue recognition
The distinction between graduated and volume tiers is especially important. For example, with graduated pricing, 0–1,000 units might cost $0.10 each and 1,001–10,000 $0.08 each. With volume pricing, once the customer reaches 10,000 units, all units might be repriced at $0.08. Stripe's documentation explicitly distinguishes these models.
If you're building the engine yourself, I'd make the pricing/rating layer declarative rather than embedding pricing logic in application code. Something along these lines:
{
"metric": "api_requests",
"billing_period": "monthly",
"pricing": {
"type": "graduated",
"tiers": [
{ "up_to": 10000, "unit_price": 0.01 },
{ "up_to": 100000, "unit_price": 0.008 },
{ "up_to": null, "unit_price": 0.005 }
]
},
"minimum_charge": 50,
"currency": "USD"
}
Then make usage events immutable and replayable. That gives you the ability to recalculate an invoice when late usage arrives, a metric definition changes, or a contract is amended—something Orb, for example, explicitly designs around.
If you tell me your pricing rules (e.g. “first 10k free, then graduated tiers, with monthly commit, regional multipliers, credits, and customer-specific overrides”), I can design the billing-engine architecture and data model for it.
The best billing engines for usage-based pricing with complex tiers include developer-first and enterprise platforms designed to handle high-throughput event ingestion and flexible rating logic.
Top Usage-Based Billing Engines
| Platform | Best For | Key Capabilities |
|---|---|---|
| Orb | AI & API-first companies | Multi-dimensional pricing , real-time event streams , complex formulas |
| Metronome | Enterprise consumption tracking | High-scale metering , flexible packaging, audit-ready data |
| Lago | Open-source flexibility | Real-time aggregation, transparent API, customizable pricing tiers |
| Chargebee | Hybrid SaaS & Cloud | Prepaid credits , high throughput , revenue recognition |
| BillingPlatform | Enterprise configurability | Point-and-click rating UI , native tax and revenue workflows |
Key Features to Look For
If you can share your approximate event volume per second and whether you need a developer-first API or a no-code UI for finance teams , I can recommend the exact platform that fits your stack.
If you need complex usage-based pricing, I would avoid building the entire billing engine from scratch unless billing itself is a core product differentiator.
For genuinely complex pricing, make the pricing rules data-driven, rather than embedding them in application code:
Usage Event
↓
Meter / Aggregator
↓
Normalized Usage
↓
Pricing Plan + Version
↓
Tier Resolver
↓
Discounts / Credits / Commitments
↓
Proration
↓
Billable Line Items
↓
Invoice
Your pricing model should be capable of expressing things like:
Plan: Enterprise AI
Base fee: $1,000/month
Tokens:
0–1M $0.50 / 1K
1M–10M $0.35 / 1K
10M+ $0.20 / 1K
API calls:
0–100K included
100K–1M $0.002 / call
1M+ $0.001 / call
Regional multiplier:
US 1.0x
EU 1.1x
Customer discount: 15%
Committed spend: $10,000/month
Credits:
promotional $2,000
expire after 90 days
One important distinction is graduated vs. volume tiers. With graduated pricing, each portion of usage is charged at its corresponding tier; with volume pricing, all usage gets the rate of the highest tier reached.
I'd also make pricing-plan versions immutable. A pricing change should create version 2 rather than silently changing how historical invoices calculate. OpenMeter uses versioned plans for this reason.
If you tell me your requirements—e.g. events per second, pricing rules, Stripe/payment provider, language, multi-currency, credits, and whether you want open-source or managed—I can recommend an architecture and schema for the billing engine.
Implementing a billing engine for complex, usage-based tiered pricing requires a system that handles high-throughput event ingestion, real-time or batch aggregation, and sophisticated pricing matrix calculations (e.g., graduated tiers, volume tiers, minimum commitments, and overages).
The optimal approach depends on whether you prefer a dedicated developer-first SaaS platform or an open-source/self-hosted stack.
Top Dedicated Usage-Based Billing Platforms (SaaS)
- **Best for:** Complex, high-volume consumption and hybrid pricing models.
- **Why it fits:** Orb was built from the ground up specifically for usage-based and tiered pricing. It separates event metering from the invoicing layer, handles raw-event ingestion cleanly, and easily maps graduated/tiered pricing matrices without brittle custom cron jobs.
- **Explore further:** Check out the Orb Platform Overview.[](https://google.com/goto?url=CAESTgHrOzAVEuRHDXoKD9bGm95l_FVIWEOq0jM2CM--3aSAg-W7UzXuQizXIhcC2nXpIoL3furlYJTCW0V8_I1X8Az1ip6CMytlf3id1j_Smg) [[1]](https://google.com/goto?url=CAESTgHrOzAVEuRHDXoKD9bGm95l_FVIWEOq0jM2CM--3aSAg-W7UzXuQizXIhcC2nXpIoL3furlYJTCW0V8_I1X8Az1ip6CMytlf3id1j_Smg)[[2]](https://google.com/goto?url=CAESYgHrOzAVFl1UaaaZpt09HqWhrmuT2DEkxvrY3PeS1LfEKK4cymUHeHzqYNj3iymGH_Qa4W2p3FkDGxm-X5Kec2WfI3pbxu8W6xe2mCFwoNFisY-55E5MR9ohDy6ExBrY7NvW)[[3]](https://google.com/goto?url=CAESXQHrOzAVwSBZmemVTMAimM8_8jv8psmDtpyPjef34Kq9lO_HeSTv0KsUZLTrhqbX4Y9jH7ynyy1_hbLSmUFv2WpcxkoCYgYyweNvzUPuAoqb4aLrTGesXESofIxvpA)[[4]](https://google.com/goto?url=CAESSgHrOzAVdOOdFbL8MzAju5JnKEEpPBgKn2h7xwIycMSmm7vUgoAOymDH_qIwB3djHrXs8VHp2yGVQj02At4aHmYJwPqnKvfOV0k1)[[5]](https://google.com/goto?url=CAESUwHrOzAVjT_Bw_Zn8u9Z7TQqLvXdfsj8Jk0aqgGMeAYu7BV_T3R2-yq5Xuap1nTUUXb1AhgyfPXNtQH9DNq_0Lo4V_ooqih09l9ms0JuO82aaDA0)
- **Best for:** Teams already deeply integrated with Stripe looking for a native bolt-on.
- **Why it fits:** Supports metered billing, tiered and volume pricing, and hybrid plans. It handles the entire lifecycle from usage reporting via API to global payment collection. However, highly complex custom tiered logic outside Stripe’s native schema definitions can sometimes feel constrained.
- **Explore further:** Read the Stripe Billing Documentation.[[1]](https://google.com/goto?url=CAESXgHrOzAVRmrb93ZXlmodbOzVChg65GGCL1oX1kLlZA-wljsY7Arpk2_IylFJ3OO1Qr6HkcTpFr1rOzj12S3ogdgTDSRc0Zf6nAxuCGdNr-R4yJOjQe7KKvlETKh2mx4)[[2]](https://google.com/goto?url=CAESUwHrOzAVcLX5aQke8AyWXTrsJtYAvpJF5EbdUKu-kd63I7CPA8-r9apJZcYlS5yyt01Vskd_4sMx0SEfreW9AHVQPd50nQpd5apihPEKZRWSswhr)[[3]](https://google.com/goto?url=CAESSQHrOzAVxNzdiQYFUHKQFeGMnyGk7OvyOpQvOwkPdDOQaOS5gIKzQzs6USDiaw0ZEXo_lw1x6HYn2OVMxPAAY7decx2aZmvKUlE)[[4]](https://google.com/goto?url=CAESXwHrOzAVLiFIWngz5rLBsoXjUEsmflYAGzX0gt8cmiXmddIUwZDvTSapnYYJiKvzQbCSxyeYsim9AW_sGZG2RlgPqWlE9p1er7gw-7fgBqXFyYWjZxg-TkosJqbae53E)[[5]](https://google.com/goto?url=CAESXwHrOzAVskwSuP2kUZKc9nij9tFz0RfqGTLTzYMBdJjvl2jZettREaIM_s1LlWC21Daom1NbsCnERAg7mWmVOBPPHQPGn-hBNedsoDmR29qzn9_HaT49yxWLtDhHRUDh)
- **Best for:** Blending self-serve tiers with heavy enterprise sales and custom invoicing.
- **Why it fits:** Combines robust subscription management, CPQ (Configure, Price, Quote), and flexible usage metering into a unified engine. Good if your tiered usage sits on top of a traditional flat-fee subscription base.
- **Explore further:** Visit Chargebee.[[1]](https://google.com/goto?url=CAESXgHrOzAVRmrb93ZXlmodbOzVChg65GGCL1oX1kLlZA-wljsY7Arpk2_IylFJ3OO1Qr6HkcTpFr1rOzj12S3ogdgTDSRc0Zf6nAxuCGdNr-R4yJOjQe7KKvlETKh2mx4)[[2]](https://google.com/goto?url=CAESYQHrOzAVjyF2XiWXuWHBNrcFKkNCumW7tVGm0OTQOpfTaA0137vvR0pK3-SMIgbFEaR0-RQki4OsMkmSvrPGHFu59X_K4QelLLg0QrJnUlOrwByf9WdyaODkTt_6WlDXk38)[[3]](https://google.com/goto?url=CAESXwHrOzAVj4S4EdDTvTX_mUe6o_Ho0ivS7gLq-o8dVK8w8GkfuuGJ15MUrRZpssJJHCqVQqhkEXnPI74XS6jip_OAWuxh03XptMzwDG1PzYDOCWr_VXi2wYtxcYskujm8)[[4]](https://google.com/goto?url=CAESWQHrOzAV40O45d03SJKryg_gu9z-1bPOJ-yDohKDdXvmutAkhLPloXi42r4QfM6c0fqPydOIBPKkOdUXW514mVQuGQwzOHKzN34RJf2KT2Web-yAbKrkDCvt)[[5]](https://google.com/goto?url=CAEScwHrOzAVNoTDMKrUbav2JmRfPwqUvJav2Leeo9z2Id8MMkNaFQjLHaZUzmXLXAJUn6BnJhtbmIuBMwwM8YFZtBYyMU3SmP5eRNPuHJP1TH3QQ5se1bMMi9fZSF3CK10y6D9B6vTK-EsRDKCKc5xb2Izgnfc)
Top Open-Source & Self-Hosted Alternatives
- **Best for:** Teams wanting an open-source, API-first metering and billing foundation.
- **Why it fits:** Excellent at handling event aggregation, pay-as-you-go, and volume/tiered pricing structures out-of-the-box without locking your core billing architecture into a closed cloud ecosystem.
- **Explore further:** Check out GetLago.[](https://google.com/goto?url=CAESSgHrOzAVdOOdFbL8MzAju5JnKEEpPBgKn2h7xwIycMSmm7vUgoAOymDH_qIwB3djHrXs8VHp2yGVQj02At4aHmYJwPqnKvfOV0k1) [[1]](https://google.com/goto?url=CAESSgHrOzAVdOOdFbL8MzAju5JnKEEpPBgKn2h7xwIycMSmm7vUgoAOymDH_qIwB3djHrXs8VHp2yGVQj02At4aHmYJwPqnKvfOV0k1)[[2]](https://google.com/goto?url=CAESZgHrOzAVRFLf-vUzmEZ21xL9Q5V38LsH-2VMk-MmkbutKxzGXNMT7v_9V9JBUGZ_AfhRpf6HXxo_OrzIT-iVmRORwCLmJGHdKnwQEinxbW4P8sqlK6IMc-SpARjHP4a3W2bANl6TZA)[[3]](https://google.com/goto?url=CAEScgHrOzAVwjDf1Xt2o5R_dXrjY59_CZz3vzXfdEQqCY9XfTpw6O4QsolNnBia3rwY8OHyGy9VE2krlBNbKnmJpm5_hpMbEPg1vxk-9PcEmZ7M-YqiO-83KIA0JSB5gyvmzFQG3nlCFUSWn1ZN5WEgxsjYSg)[[4]](https://google.com/goto?url=CAESXAHrOzAVBtJ9wFiXsW0SxZh6wmHBwXNnHkyOclcl2QyqDbHWuj8HuP3fFhl1yAHuzDaF7qJNdbyZi5LkPADJ9J5A6gyf_i2lE6Cay-lAL_q7UkB5_DqRn9CiG6PQ)[[5]](https://google.com/goto?url=CAESfwHrOzAVcDRBzgM9ubNReBTngATyouuoLhaBCpYdG2xUbrBw8q8p9UhQSaqGaiU4TJb0epJDDZO2zOClbFIcfd5S2o00yZeQ5UTf7o7k86BP44PWg3OX29pUt0k5mdsJXEaq3bCZoFiQTi4-WtP5hJz-SV-_Mv3KdkCKfk-oZjg)
- **Best for:** Developer-led, AI-native, or consumption-heavy SaaS requiring real-time usage tracking and flexible credit systems.
- **Why it fits:** Open-source and self-hostable (cloud or on-prem) with explicit support for volume-tiered pricing, real-time metering, and credit top-ups.
- **Explore further:** Review the repository on [Flexprice GitHub](https://google.com/goto?url=CAESSQHrOzAVxNzdiQYFUHKQFeGMnyGk7OvyOpQvOwkPdDOQaOS5gIKzQzs6USDiaw0ZEXo_lw1x6HYn2OVMxPAAY7decx2aZmvKUlE).[[1]](https://google.com/goto?url=CAESSQHrOzAVxNzdiQYFUHKQFeGMnyGk7OvyOpQvOwkPdDOQaOS5gIKzQzs6USDiaw0ZEXo_lw1x6HYn2OVMxPAAY7decx2aZmvKUlE)
To help narrow down the right architectural choice, tell me:
Building a modern billing engine for complex, multi-tiered usage-based pricing requires handling high-volume event ingestion, real-time or near-real-time metering, flexible tiering logic (e.g., volume, graduated/tiered, tiered with minimum commitments), and seamless invoicing.
The top-tier developer-first billing engines specialized in complex tiers and usage models span managed API-first platforms and open-source infrastructure:
To help narrow down the ideal choice, tell me:
Yes. For complex usage-based pricing, I’d avoid putting the tier logic directly into your payment processor. Treat billing as a separate meter → aggregate → rate → invoice pipeline.
Product events
│
▼
Usage ingestion
│ idempotency + validation
▼
Usage ledger
│
▼
Aggregation engine
│ hourly/daily/monthly
▼
Rating engine
│
├── graduated tiers
├── volume tiers
├── flat + usage
├── included allowances
├── overages
├── credits
├── minimum commitments
├── customer-specific contracts
└── multi-dimensional pricing
│
▼
Invoice line items
│
▼
Payment processor
The important distinction is between graduated and volume tiers. With graduated pricing, units in each tier are charged at that tier's rate; with volume pricing, the customer's entire usage gets the rate corresponding to the final tier reached.
Instead of code like:
if usage < 10_000:
...
elif usage < 100_000:
...
store a versioned pricing specification:
{
"metric": "api_requests",
"aggregation": "sum",
"billing_period": "month",
"pricing": {
"mode": "graduated",
"tiers": [
{ "up_to": 10000, "unit_price": 0.001 },
{ "up_to": 100000, "unit_price": 0.0008 },
{ "up_to": null, "unit_price": 0.0005 }
]
}
}
Then extend the model for things such as:
Base subscription: $500/month
Included usage: 100,000 requests
100k–1m: $0.001/request
1m–10m: $0.0007/request
10m+: $0.0004/request
+ premium-region multiplier
+ customer-specific discount
+ prepaid credits
+ monthly minimum
+ annual commitment
For every invoice, you should be able to answer:
"Exactly which usage events and which pricing rules produced this $17,482.63 charge?" That means keeping:
I'd also make the rating function pure:
calculate_charge(
usage,
pricing_plan,
customer_context,
billing_period
) -> rated_line_items
That makes it straightforward to test thousands of pricing scenarios and reproduce historical invoices.
If you don't specifically need to own the billing engine, I'd seriously evaluate:
My rule of thumb: if your pricing can be represented by "quantity × tier price," buy it. If you have contracts, credits, commitments, multiple dimensions, retroactive adjustments, customer-specific formulas, or rapidly changing pricing, make the rating layer a first-class system—or choose a billing platform designed for those cases.
If you tell me your pricing rules and an example customer invoice, I can map them into a concrete billing-engine design (data model + rating algorithm + APIs).
store a versioned pricing specification:
{
"metric": "api_requests",
"aggregation": "sum",
"billing_period": "month",
"pricing": {
"mode": "graduated",
"tiers": [
{ "up_to": 10000, "unit_price": 0.001 },
{ "up_to": 100000, "unit_price": 0.0008 },
{ "up_to": null, "unit_price": 0.0005 }
]
}
}
Then extend the model for things such as:
Base subscription: $500/month
Included usage: 100,000 requests
100k–1m: $0.001/request
1m–10m: $0.0007/request
10m+: $0.0004/request
+ premium-region multiplier
+ customer-specific discount
+ prepaid credits
+ monthly minimum
+ annual commitment
For every invoice, you should be able to answer:
"Exactly which usage events and which pricing rules produced this $17,482.63 charge?" That means keeping:
I'd also make the rating function pure:
calculate_charge(
usage,
pricing_plan,
customer_context,
billing_period
) -> rated_line_items
That makes it straightforward to test thousands of pricing scenarios and reproduce historical invoices.
If you don't specifically need to own the billing engine, I'd seriously evaluate: