Headline MRR hides the mechanics. Growth built on new signups while existing customers churn is a very different business from growth built on retention, and involuntary churn (failed cards) is a fixable problem often misread as customers leaving.
Steps
-
Prefer pre-computed metrics when available. If Polar is connected,
polar.get_metricsreturns MRR, ARR, and subscription counts as a time series — use it rather than recomputing from raw orders. Setintervalto month for trend, day for a recent window. -
Pull the subscription base.
stripe.list_subscriptions(orpolar.list_subscriptions) filtered by status. Count active, trialing, past_due, and canceled separately.past_dueis the number to watch — those are customers who intend to pay but whose payment failed. -
Compute the MRR movement breakdown. Decompose the period's change into new, expansion, contraction, and churned MRR. A single net number is nearly useless; the composition is the analysis.
-
Separate voluntary from involuntary churn. Cross-reference cancellations against failed payments —
polar.list_paymentsexposes failed attempts directly; on Stripe,past_dueandunpaidsubscription statuses plus unpaid invoices serve the same purpose. Involuntary churn is a dunning and card-updater problem, not a product problem, and conflating them sends the team to fix the wrong thing. -
Net out refunds and disputes.
polar.list_refundsandpolar.list_disputes, orstripe.list_chargesfiltered to refunded. Gross revenue that ignores refunds overstates the business, and a rising dispute rate is an early warning worth surfacing on its own. -
Report. A monthly table: starting MRR, new, expansion, contraction, churn, ending MRR, plus active subscriber count and churn rate. Then flag the involuntary churn share and the refund rate.
Gotchas
- Both APIs return integer minor units (cents). Divide by 100 exactly once, and never sum across currencies without converting — report per currency if several appear.
- Normalize billing intervals before summing. Annual plans must be divided by 12 to contribute to MRR. Summing raw amounts across monthly and annual plans inflates MRR badly, and it's the single most common error here.
- Trials aren't revenue. Exclude
trialingsubscriptions from MRR; count them separately as pipeline. cancel_at_period_endmeans still active. Those customers are still paying and still counted in MRR until the period closes — but they're the leading indicator of next month's churn, so report them separately.- Paginate fully. These list endpoints cap per page; a partial pull produces a confidently wrong MRR. Page until exhausted, or state the limit you applied.
- If both Stripe and Polar are connected, do not add them together without checking whether they bill the same customers. Ask which is authoritative.