← All posts
Engineering

Is usage metering enough for you at scale ?

At a few thousand events a second, naive aggregation falls over. Here's the ledger design that doesn't.

NG
Naman Gupta · ProductJun 17, 2026 · 7 min read
Is usage metering enough for you at scale ?

Usage-based billing sounds simple until you try to build it: ingest an event, add it to a running total, and bill the total. The trouble starts at the edges—late events, duplicate deliveries, retroactive corrections, and a billing period boundary that customers expect to be exact to the second.

The naive approach, and where it breaks

Our first prototype incremented a counter per customer per event type. It worked in a demo and fell over in week one of real traffic: two workers processing the same event after a network retry double-counted it, and an event that arrived four hours late landed in the wrong invoice.

// naive — breaks under retries and clock skew
ledger[customer][event] += quantity;

The fix: an append-only ledger

The fix: an append-only ledger
The fix: an append-only ledger

Every event becomes an immutable row keyed by an idempotency key the caller supplies. Aggregation is a query over that ledger, not a mutation of a counter—so a duplicate delivery is a no-op, and a late event just lands in its correct billing period retroactively, recomputing only the invoice it touches.

If you can't replay it, you can't trust it. The ledger is the source of truth; every total is a derived view.

Handling the 72-hour window

We give events up to 72 hours of lateness before they're rejected outright. Invoices in that window are marked provisional and only finalised once the window closes—which means a customer's dashboard and the finalized invoice always agree, even if a batch job upstream was slow to flush.

This is also why every SDK batches and retries with the same idempotency key — correctness at scale starts with a boring client library.

The result: the same architecture handles ten events a second or ten thousand because the aggregation logic never assumed order or single delivery in the first place.

Filed underEngineering
About the author
NG

Naman does everything that we don’t have people for, basically he runs our experimental lab and when we feel he has a new thing to pick we hire a person or build an agent to do what he was doing before. Just like his work life, he has an experimental personal life involving trekking, biking, vlogging, writing poetry, travelling to goa every other month plus scolding us, cheering us up, crying with us.

View all posts →
On this page