Stripe & Billing
Stripe MRR and Churn in Node: Subscription Metrics
Stripe revenue metrics are easier to trust when Node stores the raw event once, projects subscriptions into a current snapshot, and keeps paid invoice revenue separate from MRR.
Key takeaways for Stripe MRR and churn analytics
- Stripe Docs says webhook endpoints can listen for asynchronous events, including recurring payment success and subscription payment collection. [1]
- Stripe's event type catalog includes subscription lifecycle events such as
customer.subscription.created,customer.subscription.updated, andcustomer.subscription.deleted. [2] - The Stripe Subscription object includes
statusand subscriptionitems, which are the core inputs for an active subscription snapshot. [3] - The Stripe Invoice object includes fields such as
amount_paid,currency,status, and invoice lines, so paid revenue should be modeled separately from MRR. [4] - The Stripe Refund object includes amount, currency, charge, payment intent, and status fields, so refund events need their own revenue adjustment path. [5]
MRR should be a projection, not a webhook side effect
Stripe Docs describes webhook endpoints as a way to receive asynchronous events, including recurring payment success and subscription payment collection. [1]
That event stream is a source of facts, not the dashboard itself. A reliable Node implementation records each event ID once, keeps the payload for replay, and then derives analytics from normalized subscription and invoice rows.
The Node webhook should write an immutable event ledger first
Start with one table keyed by Stripe event ID. Store event type, object ID, created time, processing status, and a JSON copy of the payload your app actually handled.
Stripe's event type catalog lists subscription lifecycle events including customer.subscription.created, customer.subscription.updated, and customer.subscription.deleted. [2]
Use those events to maintain subscription state. Do not increment or decrement global MRR counters directly in the request handler; duplicate delivery, retries, or backfills can otherwise distort the metric.
MRR comes from active subscription items and recurring intervals
The Stripe Subscription object includes status and subscription items. [3]
In Node, project each relevant subscription into an analytics row: customer ID, subscription ID, status, currency, price ID, quantity, recurring interval, unit amount, current period, and last event ID.
Then calculate current MRR from active recurring subscriptions at read time or in a scheduled snapshot job. Normalize yearly prices to one-twelfth of annual recurring revenue only after you have checked the price interval and currency.
Want this as a drop-in kit? Stripe MRR Analytics Kit packages webhook verification, subscription syncing, MRR, ARR, churn, paid invoice summaries, refunds, tests, and a Node demo server.
Paid revenue should come from invoices, not MRR math
The Stripe Invoice object includes fields such as amount_paid, currency, status, and invoice lines. [4]
Keep paid revenue in a separate monthly rollup from MRR. MRR is a forward-looking recurring-rate snapshot; paid invoice revenue is cash movement after invoices are finalized and paid.
This separation prevents the classic dashboard bug where plan upgrades, prorations, annual contracts, and retries look like sudden revenue changes even when the underlying subscription base has not changed in the same way.
Churn needs subscription status plus refund adjustments
Use subscription lifecycle events to mark canceled or ended subscriptions in your analytics table, then calculate churn over a defined cohort window. The formula is your business choice, but the event inputs should be stable and replayable.
The Stripe Refund object includes amount, currency, charge, payment intent, and status fields. [5]
Model refunds as revenue adjustments instead of churn by default. A refund can be a support credit, duplicate charge fix, or partial reversal; a canceled subscription is the stronger signal that a customer left recurring revenue.
This article is informational and is not a substitute for a security, billing, tax, or legal review of your own product.
CI Tripwire has not commissioned independent expert review of this article. Read more about the organization byline at contributors and the source posture at sourcing.
Corrections can be routed through the corrections note. Sources: 5 entries, Stripe documentation, last reviewed 2026-06-09.
Sources
- Stripe Docs, Receive Stripe events in your webhook endpoint.
- Stripe API Reference, Event types.
- Stripe API Reference, The Subscription object.
- Stripe API Reference, The Invoice object.
- Stripe API Reference, The Refund object.