I once inherited a subscription business where the finance team was confident everything balanced. Yet month after month we were missing nearly 15% of expected cash from billed revenue. It wasn’t fraud or a wild churn spike — it was a slow bleed of edge cases, mismatched systems and a few automation assumptions that never survived scale.
Finding that leak required a simple, repeatable approach I now call the three-check reconciliation playbook. It’s designed for product-led SaaS, subscription e-commerce and any business that bills customers on a recurring schedule. The goal is practical: run three focused checks that surface where cash is falling out of the system, quantify the impact, and create priority fixes you can deploy within weeks.
Why the three-checks? What makes 15% possible?
Subscription systems span payment gateways (Stripe, Adyen), billing engines (Chargebee, Recurly, Zuora), CRM (HubSpot, Salesforce), and accounting (Xero, QuickBooks). Each handoff is a place cash can be lost, delayed, or misrecorded:
Individually these issues often represent small percentages. Combined, they add up. The three-check playbook isolates failures at each handoff so you can measure and fix them quickly.
Check 1 — Payment gateway vs. Billing engine
What I check first is whether the payments collected by your gateway match what the billing system thinks was paid. This catches failed payments, partial payments, gateway fees and unapplied refunds.
How to run it:
Red flags you’ll see:
Quick SQL example (pseudocode):
<code>SELECT b.invoice_id, b.amount, g.gateway_amount, g.statusFROM billing_ledger bLEFT JOIN gateway_transactions g ON b.payment_id = g.idWHERE g.id IS NULL OR b.amount != g.gateway_amount;</code>
Check 2 — Billing engine vs. Customer subscriptions
Billing engines can produce invoices that don’t reflect actual subscription state: wrong plan, overlapping subscriptions, failed proration logic, or coupons applied multiple times.
How to run it:
Common defects:
Example metric to compute:
Check 3 — Revenue ledger vs. Cashbook (Accounting)
Finally, you must confirm that recognized revenue and cash receipts in the general ledger (GL) reconcile to what billing and gateway report. This catches timing issues, manual journal entries, and FX or bank fees that weren’t accounted for.
How to run it:
Points to watch:
Putting numbers to the leak
To be persuasive and operational, measure and communicate the leak in three slices:
Small example table that I used to present to leadership:
| Metric | Value (30 days) | Notes |
|---|---|---|
| Invoices billed | £200,000 | Gross invoice total |
| Payments collected (gateway) | £175,000 | After failed payments/refunds |
| Payments posted (billing) | £165,000 | Missing £10k misapplied/ungrouped |
| Cash in GL | £170,000 | Bank fees & timing differences |
| Observed leak | 15% (approx) | Combined effect of failures & mis-postings |
Fixes that scale — priorities and quick wins
After you identify the root causes, prioritize fixes by cash impact and implementation effort:
KPIs to track weekly
When we started tracking these, the daily unmatched payments list became a small, actionable queue. We reduced the leak from 15% to under 2% within three months by pairing a few automation fixes with a weekly reconciliation runbook.
If you want, I can share a starter SQL template and a spreadsheet layout I use to automate the three checks (gateway extract → billing ledger → GL). I also include a short list of webhook fields you should capture from Stripe/Adyen to avoid future mismatches.