Docs

How we calculate MRR and churn

How RevenueSheet turns subscription intervals into monthly recurring revenue and logo churn.

MRR

Monthly recurring revenue is the sum of each eligible subscription’s billed amount converted to a monthly rate:

  • Monthly: as billed
  • Quarterly: amount divided by 3
  • Biannual (twice a year): amount divided by 6
  • Yearly / annual: amount divided by 12
  • Biennial (every two years): amount divided by 24
  • Weekly: amount times 52, divided by 12
  • Daily: amount times 365, divided by 12

Vendor interval labels are normalized first so Lemon Squeezy month-plus-count plans (for example month times 3) and Gumroad quarterly / yearly labels map to the same periods.

By default only subscriptions with status active count toward total MRR. Paused subscriptions are not included.

Why your MRR may differ from Polar’s

Polar’s public Analytics docs define MRR as the sum of every ongoing subscription’s net amount, normalized monthly (yearly plans divided by 12). Trialing subscriptions are excluded. Paused and past-due subscriptions are included until the subscription actually ends (Polar Analytics, checked 2026-10-11).

RevenueSheet defaults the other way: only active counts toward total MRR. Paused is out. Past-due and trialing stay out unless you turn on the sidebar toggle Include trialing + past due in MRR, which adds those statuses into the total. We also combine Polar with other stores in one sheet, so a combined figure will not match Polar’s Polar-only dashboard even when eligibility rules align.

Refunds

Over a trailing window (default 30 days):

  • Refund amount and count sum every refund row whose created timestamp falls inside the window.
  • Order revenue for the rate sums order amounts in the same window, skipping failed orders.
  • Refund rate is refund amount divided by order revenue (0 when order revenue is 0).

That summary does not special-case chargebacks. Separately, when the add-on builds a 30-day net revenue figure for the dashboard, it skips orders marked refunded, chargeback, or failed, then subtracts refund amounts in the window. Refund and chargeback rows also land on the Refunds tab from each source importer when the API returns them.

MRR itself is subscription-based. Refund and chargeback totals do not change an active subscription’s monthly contribution until that subscription’s status or amount changes on the next sync.

Churn

Logo churn over a trailing window (default 30 days) ending at “now”:

rate = cancellations in the window ÷ subscriptions that were active at the window start

A subscription counts as active at the window start if it was created before the window and had not cancelled before that start. Cancellations inside the window increment the numerator. The same math on the previous window produces the percentage-point change shown on the dashboard.

This is customer (logo) churn, not dollar churn. New subscriptions in the window are tracked separately.

For the curious

Interval conversion: toMonthlyAmount / toMonthlyFromUnitCount in addon/src/lib/intervals.ts, with vendor strings via normalizeBillingInterval and intervalFromUnitAndCount.

Sidebar toggle Include trialing + past due in MRR maps to includeTrialingPastDue in addon/src/metrics/mrr.ts.

Refund summary: computeRefundSummary in addon/src/metrics/refunds.ts. Dashboard net revenue: sumNetRevenue30d in addon/src/sync.ts.

Logo churn: cancelled_in_window / active_at_window_start in addon/src/metrics/churn.ts.

Related