01
Billing engine
Stripe as the pricing, proration and invoicing authority, with a thin local mapping between tenants, plans and Stripe objects. Exactly one implementation of proration now exists, and we did not write it.
CASE 10
8 weeks
Billing stopped being an existential risk.
A Series A SaaS had a homegrown billing system quietly losing money — missed dunning, hand-written invoices, proration computed three different ways. We replaced the engine with a Stripe-backed one, piped real usage metering into it, and gave customers self-service, without a single day of billing downtime.
THE PROBLEM
Homegrown billing was breaking in subtle, expensive ways: missed dunning, manual invoices, proration mistakes, and no self-service for customers.
Failed payments were retried by a cron job that had silently stopped firing after a deploy months earlier. Nobody noticed, because nobody had a dashboard for it, and involuntary churn was being read as ordinary churn.
Mid-cycle plan changes were prorated by a function written twice — once in the API and once in the admin panel — which disagreed. Finance reconciled the difference by hand and by feel.
Every enterprise invoice was assembled manually in a spreadsheet, so month-end consumed several days of the founder's time and produced numbers that never quite matched the ledger.
CONSTRAINTS WE WORKED UNDER
WHAT WE DID
Replaced the custom billing with a Stripe-backed engine — subscriptions, usage metering, proration handled correctly.
Customer self-service portal: update card, download invoices, upgrade/downgrade plans without emailing support.
Usage metering piped into Stripe from their event stream so invoices are always right.
Dunning and retry schedules tuned against their historical churn data.
ARCHITECTURE
01
Stripe as the pricing, proration and invoicing authority, with a thin local mapping between tenants, plans and Stripe objects. Exactly one implementation of proration now exists, and we did not write it.
02
Their existing event stream aggregated into billable units, deduplicated by idempotency key and pushed to Stripe on a schedule with a reconciliation pass. Late events land in the correct period rather than being silently dropped.
03
Signed webhook handling into a queue with idempotent processors and a dead-letter path. Every state change is derived from Stripe's events rather than assumed after an API call — the failure mode that caused most of the original system's drift.
04
Card updates, invoice history, plan changes with a preview of the exact proration before confirming, and seat management. Support tickets that used to be billing questions largely stopped existing.
05
A dual-write and shadow-compare period: the new engine computed invoices alongside the old system, differences were reported daily, and cutover only happened once the diff stayed empty.
KEY DECISIONS
WHY
Every homegrown billing system converges on reimplementing proration, tax and dunning badly. The strategic move was deleting that surface area, not maintaining it better.
TRADE-OFF
Pricing experiments now live within Stripe's model, and vendor lock-in is real. The team judged that acceptable versus owning invoice arithmetic with four engineers.
WHY
The only trustworthy proof that new billing is correct is agreement with old billing on real accounts across a full cycle.
TRADE-OFF
Added two weeks and required dual-write plumbing that was thrown away afterwards. It surfaced four genuine discrepancies before a customer ever saw one.
WHY
Quietly re-pricing legacy accounts during a technical migration is how a billing project becomes a churn event.
TRADE-OFF
More plan objects to carry, including some that will never be sold again. Cheap insurance.
THE HARD PARTS
We found the dead dunning job during the audit, not the build. Restarting retries recovered a meaningful slice of accounts that had been written off as churned — the fastest payback in the engagement, delivered in week one.
Their pipeline could deliver events hours late, which under naive aggregation meant under-billing. Period-aware aggregation with a reconciliation window fixed it, with a deliberate rule that late events never retroactively increase a closed invoice — they roll forward.
Three were the old system being wrong, one was our mapping. Finding them against real accounts before cutover is exactly why the shadow period existed, and it turned finance from sceptics into advocates.
HOW IT RAN
01
Read the existing implementation end to end, catalogued every plan, discount and grandfathered term, and documented what was actually broken versus merely ugly.
02
Stripe object model, tenant mapping, webhook processing, and the dual-write shadow-compare harness.
03
Usage aggregation with reconciliation, self-service portal, and dunning schedules tuned against their historical recovery data.
04
A full cycle in shadow, discrepancy resolution, then cutover with the old system left readable but inert.
OUTCOME
0
Manual invoices after cutover
0
Minutes of billing downtime during migration
4
Real discrepancies caught before any customer saw them
Days → 0
Founder time spent on month-end
Zero manual invoices. Revenue reporting matches the ledger for the first time. The founder can reason about churn instead of worrying about billing bugs.
Recovered involuntary churn was the immediate financial story: a dunning process that actually runs turns a category of loss back into revenue.
The strategic outcome was smaller surface area. Billing went from the scariest part of the codebase to a mapping layer a new engineer can read in an afternoon.
STACK
APPLICATION
BILLING
MIGRATION
OPS
HANDOVER