%20(1).png)
Automated Billing Systems: Architecture, Risks, and Limits
An automated billing system runs well on scheduled rules until pricing depends on the real-time state. Here's the architecture, and where it breaks.
What billing mediation is, why AI usage pushes it harder than traditional SaaS, the four functions, a worked event example, and build vs. buy guidance.
%20(1).png)
An internal ops dashboard we built recomputed usage totals every hour using its own rounding logic, different from what the billing pipeline used downstream. The two numbers drifted by about 3% a month, which was small enough that nobody flagged it for two quarters straight.
By the time someone found it, the discrepancy came back to a rounding rule nobody remembered having written. That drift is exactly what billing mediation exists to catch before it compounds for months.
Billing mediation is the layer that takes raw usage events, the kind your product emits constantly, and turns them into clean, billing-ready records. It sits between the systems that generate usage and the systems that price and invoice it.
At a basic level, mediation starts by:
Rating and entitlement enforcement are separate functions that operate on the output of mediation. They run as downstream processes, outside the mediation layer itself.
AI products push mediation harder because the volume and velocity of billable events increase by orders of magnitude.
A traditional SaaS product might generate one billable event per login, per API call, or per month of a subscription.
An AI product priced on tokens can generate hundreds of billable events in a single request, and thousands in a single session.
That volume creates real failure modes. Events arrive out of order. The same event gets emitted twice because of a retry. A model change alters what counts as a billable unit halfway through a billing period.
These are the default conditions mediation has to be designed around, and they show up constantly at this volume.
Mediation breaks down into four jobs: capturing raw events at volume, cleaning and deduplicating them, aggregating them into billable totals, and syncing the result to every system downstream.
The mediation layer has to collect raw usage events from wherever they're generated, whether that's application logs, API gateways, or agent runtimes, without dropping data during a traffic spike.
For AI products, that spike can arrive inside a single customer's session. Ingestion typically runs through a message queue or streaming pipeline instead of direct writes to a database, since a burst of events during a single generation job can outpace what a synchronous write path can absorb.
Ideally, you don’t want to learn this the hard way after a single customer's batch job takes down an ingestion endpoint that had only ever been load-tested against steady traffic.
Raw events rarely arrive in a consistent format. Different services timestamp differently, use different field names, and occasionally emit the same event twice because of retries or at-least-once delivery guarantees.
Normalization converts these into one standard shape, typically a canonical event schema with a defined unit type, timestamp format, and account identifier.
Deduplication relies on an idempotency key, typically a hash of the event's source, timestamp, and payload, checked against a short-lived store before the event is accepted.
If you skip this step, duplicate retries look identical to legitimate usage. Finance is usually the one who catches it, asking why a customer's bill jumped.
Individual events are rarely what get billed. Customers are charged for the sum of tokens across a session, a day, or a billing period.
This layer groups events into billable meters using a defined aggregation window, and applies the transformations (summing, averaging, and converting units) that turn a stream of raw events into a small number of meaningful totals.
Getting the aggregation window wrong is an easy mistake. Align it to the billing cycle instead of the customer's actual usage pattern, and you can end up splitting one continuous session across two invoices.
Once usage is clean and aggregated, it has to reach every system that depends on it. That means the rating engine, the billing platform, the customer-facing usage dashboard, and often the entitlements layer tracking how much of a plan's allocation remains.
This generally means publishing aggregated records to each downstream consumer independently, with retry logic and dead-letter handling for the ones that fail to process them.
Keeping all of these in sync matters as much as getting the math right in the first place. The support tickets I remember most were about two systems showing two different numbers for the same account.
Billing mediation works by taking a raw usage event through four stages: ingestion, normalization and deduplication, aggregation, and synchronization, before it reaches billing or entitlements.
Let’s look at an example for a single request where a customer's AI feature makes a single model call with 2,400 input tokens and 600 output tokens.
The application emits a raw event as soon as the call completes. At this stage, it is only a log line with a service name, a rough timestamp, and a token count buried in a JSON blob that was never designed for billing.
Ingestion picks the event up from the queue and passes it to normalization, which reshapes it into a canonical structure.
This includes a defined event ID, an account identifier resolved from the API key that made the call, a standardized timestamp, and separate fields for input and output tokens.
Deduplication then checks the event's idempotency key against a short-lived store. If the same event has already come through, it gets dropped here before being counted twice. In this case, it had not.
Aggregation groups this event with every other token event from the same account inside the current billing period, running a sum across input tokens and a separate sum across output tokens.
The two totals get converted into whatever unit the pricing model uses, credits, in this example, using a defined conversion rate.
The updated total gets pushed to three places at once:
These four steps take an afternoon to build correctly once. Making them hold up across 100,000 events a day, in the right order, exactly once each, takes considerably longer.
The event we just walked through looks different at each stage. Here's what that looks like in code.
A raw event, before mediation touches it, is often inconsistent and service-specific:
json
{
"svc": "inference-worker-3",
"ts": "1721043200",
"acct": "cust_88213",
"usage": { "in": 2400, "out": 600 }
}
After normalization, the same event conforms to a canonical schema that every downstream system can read the same way:
json
{
"event_id": "evt_9f8a2c1b",
"account_id": "cust_88213",
"ts": "1784127200"
"unit_type": "tokens",
"quantity": {
"input": 2400,
"output": 600
},
"source": "inference-worker-3",
"idempotency_key": "sha256:4a7d..."
}
The specific field names will vary by system, but the structure matters more than the naming.
You need a stable event ID for deduplication, a resolved account identifier in place of a raw service tag, a standardized timestamp format, and a typed quantity field that the aggregation layer can sum without guessing at units.
Most billing platforms, Stripe included, were built around a model where usage arrives in comparatively low volume: monthly API call counts, seat counts, storage totals. They handle that volume well.
The mediation problem changes shape entirely when usage means a token-level event stream firing continuously during a single customer session, and that's a different engineering problem than pricing and invoicing, which is what those platforms were designed to solve.
Those tools are doing exactly what they were built to do. The mediation problem for high-velocity, token-level usage is closer to a data engineering problem than an accounting one, and it tends to sit upstream of whatever billing platform a company already uses.
For a product with a single, well-defined usage metric and a handful of data sources, a homegrown mediation pipeline is often the right call.
I've seen a scheduled job that pulls, cleans, and aggregates usage once a day hold up for years at that size, and there's no reason to replace something that's working. Although that setup holds up for a while, the strain shows up under specific conditions.
Usage data starts coming from multiple independent sources that don't agree on the format. The strain shows up under three specific conditions:
None of this shows up in a company's first year.
I've watched it surface when a second product line starts emitting usage in its own format, or when a customer disputes an invoice, and nobody on the team can trace the line item back to the events that produced it.
Whether you build this or buy it, the same handful of things separate a mediation layer that holds up from one that falls behind without anyone noticing right away.
This is the bar any mediation layer, homegrown or purchased, has to clear before the rest of the billing stack can trust the numbers it's getting.
Billing mediation is the layer most usage-based systems underinvest in until a reconciliation problem forces the issue.
Getting it right with high-volume ingestion, clean normalization, accurate aggregation, and reliable synchronization makes all the other layers, like rating, entitlements, and invoicing, meaningfully more trustworthy.
Here's how Stigg approaches the mediation layer specifically, as part of being the usage runtime for AI products where entitlements, credits, usage limits, and spend governance are enforced synchronously in the request path:
You don't have to adopt the whole runtime to fix mediation. The ingestion, normalization, and sync components can be used on their own, so mediation is a layer you add.
The mismatch that costs you an invoice is usually smaller than a rounding error, until it isn't. See the Stigg docs for details on usage, ingestion, and mediation.
The main difference between billing mediation and metering is scope. Metering records that usage happened. Mediation takes that recorded usage, along with data from other sources, and cleans, normalizes, and aggregates it into something a billing or entitlements system can use directly.
Not necessarily. It depends on your usage data sources. Usage-based billing tools handle pricing and invoicing, while data cleanup is a separate function. A single, well-structured event source may not need a dedicated mediation layer, but multiple sources with inconsistent formats typically do.
The main difference between billing mediation for AI products and for traditional SaaS is volume and velocity.
AI usage, priced on tokens or agent actions, can generate thousands of billable events in a single session, while traditional SaaS usage arrives in predictable, low-frequency batches. This substantially changes both the ingestion and deduplication requirements.
Yes, billing mediation reduces one major source of revenue leakage, though not every source. Dropped events, duplicate events, and misaligned usage records are common causes of under-billing, and a mediation layer designed to catch them addresses that specific problem directly.
Mediation sits earlier in the pipeline than entitlements enforcement. Mediation cleans and structures usage data after it occurs, while entitlements enforcement decides whether a request is allowed before it happens. Both matter, on different timelines.