All guides
Billing architecture

One Report. Five Systems. One Number Must Survive.

A report leaves your product as one fact and crosses five billing decisions. See how to keep its identity intact until it becomes an invoice line.

Updated 2026-08-15

TRACE: REPORT 87

The same fact, all the way to the invoice.

10:42Report 87 completed
10:42Recorded once
MONTH ENDInside allowance
INVOICESAR 0 for this report
Good architecture preserves more than the number. It preserves the reason.

Report 87 completed at 10:42. By the time it reaches the invoice, five systems have had a chance to rename it, count it twice, apply the wrong plan, or lose it completely.

Billing architecture is the discipline of letting that report travel without changing its identity. The product owns what happened. The commercial model owns what it means for the bill. Confuse those two, and every future pricing change becomes a data problem.

Give the fact one identity

Report 87 produces 3 kinds of information:

TypeExampleCan it change later?
Product factReport completed at 10:42No
Commercial decisionFirst 100 reports are includedYes, in a new version
Financial resultThe report was included and added no chargeNot after invoice finalization

Do not rewrite the old fact to match a new rule. Preserve the action as it happened and apply the plan and price version that were effective at that time.

Let the catalog change without rewriting history

The catalog connects the product, feature, plan, price, meter, and included limit. Every material change needs a new version.

When the Growth price increases, new customers begin on the new price. Noura’s subscription still references the terms she accepted, and every old invoice remains explainable.

An event needs the customer’s commercial context

An event alone does not know whether the customer is in a trial, on Growth, or upgraded in the middle of the period. The subscription supplies the plan, effective date, status, and next scheduled change.

Represent activation, upgrade, downgrade, renewal, and cancellation as dated state changes. A single is_paid field cannot tell that story.

“Can they?” and “how much?” are different questions

The entitlement answers: can this customer use the feature now?

The meter answers: how many successful actions happened in the period?

The price answers: what does that quantity do to the invoice?

Keeping those decisions separate lets you change a limit or price without rebuilding the feature, and roll out a feature gradually without changing what the customer bought.

Retries must move the fact, not copy it

Every event needs a stable identity, timestamp, customer, and unit. If delivery fails, send it again with the same identity. The retry delivers the same fact; it does not create another unit.

The meter then aggregates events inside the billing period and applies the price, allowance, and tiers. Preserve intermediate results so support can explain the amount without rebuilding the calculation elsewhere.

The invoice is where the story becomes permanent

At the end of the period, the invoice combines the subscription price, usage, discounts, tax, and adjustments. After finalization, do not silently rewrite its lines. A later change appears as an explicit adjustment or refund.

Payment comes next. A payment attempt settles the amount; it does not define it. That separation lets you retry collection or change providers without changing commercial history.

Test the moments that make numbers disagree

  • The same event arrives twice;
  • an event arrives after the period closes;
  • the price changes mid-month;
  • the customer upgrades and payment of the difference fails;
  • a finalized invoice needs a correction;
  • one meter fails without affecting other customers.

The architecture is ready when you can start with any amount and identify the event, subscription, price, and decision that produced it.

Tirdad provides these pieces as one system: catalog, subscriptions, entitlements, usage metering, usage units, invoicing, and collection. Your team stays focused on the part of the product that makes it different instead of building a billing runtime around it.

See the runtime in detail: read From Product Usage to an Invoice with Tirdad