“Billing” is really four jobs on four clocks
Enforcement must be fast and can be slightly wrong. Invoices must be exact and can be slightly late. Same usage, two systems.
When is the event ID minted?
Bad: In the send function
Each retry gets a fresh ID: a second charge.
Good: Once, when the work completes
Store it with the event in the spool; resend it unchanged.
Delivered twice, counted once
No network delivers exactly once. So deliver at least once, record the ID and add the quantity in one transaction, and skip IDs already seen.
23k/s
usage events, at 2 billion calls a day
That’s 23× Stripe’s standard limit. Roll up at the source: per-minute totals per tenant, each with a deterministic ID, about 28× fewer.
Used in October, arrived in November. Which invoice?
Event time picks the period. Usage arriving within the grace period still makes October’s invoice; later usage becomes a labelled line on the next.
Volume tiers price every call at the tier the total lands in. 1,000,000 calls, ₹3,00,000. One more?
One call later
₹2,00,000.20. Every call drops to ₹0.20. Customers pad usage to cross cliffs; graduated bills never drop.
Why quota counters can’t write invoices
- Nodes sync every few seconds, so quotas overshoot
- A Redis failover loses recent increments
- Counter store down? The gateway fails open
- They count attempts, even requests that fail
Remember
Mint each event’s ID once, dedupe into exact totals, invoice after a grace period. Quotas run on separate, approximate counters.