#Billing
Articles about Billing — exploring patterns, best practices, and real-world implementations in production systems.
8 posts tagged with billing. ← Blog home
The billing system's last responsibility is proving itself: that every invoice matches money that actually moved, that revenue is recognized when it's earned rather than when it's charged, and that the metrics the business runs on — MRR, churn, net revenue retention — derive from billing data by defined rules rather than by whichever spreadsheet ran last. Revenue integrity is where billing engineering meets accounting, and the systems that skip it get audited into building it retroactively.
Revenue integrity closes the series: reconciliation across billing, processor, and settlement with a short owned exception queue; revenue recognition (charging is not earning — emit service periods and linkage so deferral is computable); and MRR with movements as versioned derivations from the state machine itself.
Billing's defining property — post 1 called it time-dominance — makes it nearly untestable by ordinary means: the interesting behavior happens at renewals, trial expiries, grace-window closures, and anniversary boundaries, none of which occur during a test run unless the test controls time itself. The teams that trust their billing systems all converged on the same answer: make the clock an injectable dependency, simulate months in milliseconds, and pin correctness with golden invoices.
Billing becomes testable when time becomes an injected dependency: simulated clocks drive month-long lifecycles in milliseconds, golden invoices pin the money to the cent with diffs as review artifacts, re-derivation audits check production continuously, and property tests cover the proration arithmetic.
Scattered through most SaaS codebases is the same bug factory: `if plan == "pro"` checks guarding features. They work until the first pricing change, when "pro" splits into three plans, grandfathered customers keep old capabilities, sales grants an exception, and a trial needs temporary access — and suddenly product code is re-implementing billing logic badly. Entitlements are the missing layer: a dedicated system answering "may this customer do X?" so that product code never asks about plans at all.
Entitlements decouple what customers can do from what they pay: features (boolean, limit, quota), grants with sources and validity, and resolution behind one fast cached check — with plans demoted to versioned bundles. Pricing re-packages freely without product deploys, and exceptions become auditable.
The invoice is where billing's abstractions become a legal document and an attempted charge. Everything upstream — price versions, metered totals, prorations — converges into line items a human must be able to read and a regulator must be able to audit; then the system has to actually collect, which means confronting the fact that a meaningful fraction of payments fail. Invoicing is document engineering; collection is failure engineering; revenue requires both.
The invoice is an immutable derivation — re-derivable from versioned inputs, frozen at finalization, corrected only by new documents. Collection is failure engineering: dunning that distinguishes hard from soft declines, schedules retries deliberately, and treats the payment-update email as part of the machinery.
A subscription looks like a row with a plan and a date. It behaves like a state machine with a dozen states, transitions triggered by humans, payments, and the calendar, and money consequences on nearly every edge. Teams that model the lifecycle explicitly handle upgrades, trials, and cancellations as transitions with rules; teams that don't accumulate booleans — `is_trial`, `is_paused`, `cancel_at_period_end` — until no one can say what state a customer is actually in.
A subscription is a state machine — trialing, active, past-due, paused, canceled-now vs at-period-end — where every edge answers four questions: trigger, money, entitlements, clock. Proration arithmetic with encoded policies, and scheduled transitions as first-class records so future state is queryable.
Usage-based pricing has a humble prerequisite: you must count correctly. Not approximately — correctly, at whatever volume success brings, across retries, duplicates, late arrivals, and clock skew, because every counted unit is money and every miscounted one is a dispute. Metering is stream processing where the aggregation result appears on an invoice, and that destination changes every engineering trade-off.
Metering is stream processing with invoice-grade obligations: deterministic source-minted idempotency keys, dedup at the door, event-time aggregation into exactly one billing period with a grace window, compensating events instead of mutation — and two meters: streaming approximate for the product, batch exact for the invoice.
Every pricing page looks simple: three tiers, a slider, maybe "contact us." The code behind a pricing page that can evolve is anything but — because pricing changes faster than software, old customers keep old deals, and the moment a price lives as a constant in application code, every experiment becomes a deploy and every grandfathered customer becomes an if-statement. The foundational move of billing engineering is modeling the catalog as versioned data.
Flat, per-seat, graduated vs volume tiers (not the same thing), usage, hybrids — one abstraction: price is versioned data mapping quantity-over-a-period to an amount. Immutable price versions make grandfathering default behavior and invoices re-derivable; application code never holds an amount.
Most teams treat billing as a form you fill in at a payment provider — until the first incident teaches them otherwise. Billing sits at the intersection of money, state machines, and time: it must be exactly right, it changes under regulation and pricing strategy, and every bug is either lost revenue or an angry customer charged twice. This series treats monetization as the engineering discipline it actually is, from pricing models to metering to revenue integrity.
Billing is a correctness-critical, time-dominated system, not a form at a payment provider. The failure modes — public overcharging, silent undercharging, double-charges, price drift — demand financial-grade engineering, and the AI era raises the stakes: usage-based pricing makes metering and entitlements load-bearing. Opens an 8-post series.
All posts on this site are written by Pratik Dhanave, an Agentic AI Architect with 7+ years building production distributed systems, multi-agent AI platforms, and cloud-native infrastructure. About the author → Each article includes working code, architecture diagrams, and references to the specific frameworks and standards discussed. Browse the blog or explore related topics using the tag cloud above.