xmetric / Use cases

MRR and churned MRR from a Stripe subscriptions export

MRR is the monthly value of every subscription whose status is active or past_due: amount times quantity, with annual plans divided by 12. That is how Stripe's own Billing analytics defines it. From the subscriptions export the same sum by product, by start month and by the month a subscription ended gives your MRR, new MRR and churned MRR. Drop your export below, or copy the Tableau formula or the SQL.

Drop your Stripe subscriptions CSV

MRR now, new MRR by month and churned MRR by month

A made-up subscriptions export, snapshot on 2026-10-01: 90 subscriptions on monthly and annual plans with seats, cancellations, trials, past-due and expired ones. The sample is synthetic and uses column names typical of the Dashboard's subscriptions export. Computed from stripe-subscriptions.csv (90 rows of made-up data). The Tableau calculation and the SQL below both produce these numbers.

MRR now

MRRARRPaying customersMRR per customer
7,467.3389,608.0073102.29

MRR by product

ProductSubscriptions in MRRMRRShare of MRR
Team354,352.8358.3%
Business112,601.5034.8%
Starter27513.006.9%

New MRR by start month, and how much is still in MRR

StartedNew subscriptionsNew MRRStill in MRRKept
2026-01101,289.001,031.0080.0%
2026-02131,245.00722.0058.0%
2026-037659.00640.0097.1%
2026-045482.83463.8396.1%
2026-05111,231.501,212.5098.5%
2026-066405.50307.5075.8%
2026-075334.00315.0094.3%
2026-08131,968.501,839.5093.4%
2026-0914936.00936.00100.0%

Churned MRR by the month a subscription ended

EndedCanceled subscriptionsChurned MRRAvg months before canceling
2026-042485.002
2026-06119.003
2026-072277.004.5
2026-08357.003.33
2026-093246.003.67

Recompute it from your CSV

Export your subscriptions from the Stripe Dashboard and drop the CSV here. Match the columns if your export uses other names. The calculation runs in this browser; nothing is uploaded.

No file loaded yet. You can also drop a CSV on this box.

What a subscriptions export can and can't tell you

The export is a snapshot: one row per subscription, with its price, quantity and status today. That's enough for MRR now, for new MRR by the month a subscription started, and for churned MRR by the month it ended. It can't show expansion or contraction, because a subscription that moved from Team to Business appears once, at Business. For upgrades and downgrades, use Stripe's Customer MRR changes report (Billing overview > Report downloads) or your invoices.

The Kept column compares each month's new MRR with what those subscriptions still bring in. A month whose new MRR is mostly gone is a cohort to look at; for customer counts month by month, see cohort retention from the payments export.

Export subscriptions from the Stripe Dashboard

  1. In the Stripe Dashboard, open Billing > Subscriptions.
  2. Click Export and download the CSV. Include canceled subscriptions: without them there is no churn to count.
  3. Drop it in the box above.

Stripe documents the subscription fields and statuses in its API reference and the MRR definition in its Billing analytics docs, checked 2026-10-18. It doesn't publish the export's column headers. The sample uses headers typical of the export (Customer ID, Product, Quantity, Interval, Amount, Status, Created (UTC), Ended At (UTC)); if yours differ, match them in the box.

The Tableau calculation

MRR now

No dimensions in the view: each calculation returns one number for the whole file.

// Monthly value
CASE [Interval] WHEN 'year' THEN [Amount] * [Quantity] / 12 WHEN 'week' THEN [Amount] * [Quantity] * 52 / 12 WHEN 'day' THEN [Amount] * [Quantity] * 365 / 12 ELSE [Amount] * [Quantity] END

// In MRR
[Status] = 'active' OR [Status] = 'past_due'

// MRR
SUM(IF [In MRR] THEN [Monthly value] ELSE 0 END)

// ARR (MRR x 12)
SUM(IF [In MRR] THEN [Monthly value] ELSE 0 END) * 12

// Paying customers
COUNTD(IF [In MRR] THEN [Customer ID] END)

// MRR per customer
SUM(IF [In MRR] THEN [Monthly value] ELSE 0 END) / COUNTD(IF [In MRR] THEN [Customer ID] END)

MRR by product

On Rows: [Product]. Each calculation below is one column.

// Monthly value
CASE [Interval] WHEN 'year' THEN [Amount] * [Quantity] / 12 WHEN 'week' THEN [Amount] * [Quantity] * 52 / 12 WHEN 'day' THEN [Amount] * [Quantity] * 365 / 12 ELSE [Amount] * [Quantity] END

// In MRR
[Status] = 'active' OR [Status] = 'past_due'

// Subscriptions in MRR
COUNTD(IF [In MRR] THEN [id] END)

// MRR
SUM(IF [In MRR] THEN [Monthly value] ELSE 0 END)

// Share of MRR
SUM(IF [In MRR] THEN [Monthly value] ELSE 0 END) / MIN({ FIXED : SUM(IF [In MRR] THEN [Monthly value] ELSE 0 END) })

New MRR by start month, and how much is still in MRR

On Rows: DATETRUNC('month', [Created (UTC)]). Each calculation below is one column.

// Monthly value
CASE [Interval] WHEN 'year' THEN [Amount] * [Quantity] / 12 WHEN 'week' THEN [Amount] * [Quantity] * 52 / 12 WHEN 'day' THEN [Amount] * [Quantity] * 365 / 12 ELSE [Amount] * [Quantity] END

// In MRR
[Status] = 'active' OR [Status] = 'past_due'

// Started paying
[Status] <> 'trialing' AND [Status] <> 'incomplete' AND [Status] <> 'incomplete_expired' AND [Status] <> 'paused'

// New paying subscriptions
COUNTD(IF [Started paying] THEN [id] END)

// New MRR
SUM(IF [Started paying] THEN [Monthly value] ELSE 0 END)

// Still in MRR
SUM(IF [In MRR] THEN [Monthly value] ELSE 0 END)

// Share of new MRR still in MRR
SUM(IF [In MRR] THEN [Monthly value] ELSE 0 END) / SUM(IF [Started paying] THEN [Monthly value] ELSE 0 END)

Churned MRR by the month a subscription ended

On Rows: IF [Status] = 'canceled' THEN DATETRUNC('month', [Ended At (UTC)]) END. Each calculation below is one column.

// Monthly value
CASE [Interval] WHEN 'year' THEN [Amount] * [Quantity] / 12 WHEN 'week' THEN [Amount] * [Quantity] * 52 / 12 WHEN 'day' THEN [Amount] * [Quantity] * 365 / 12 ELSE [Amount] * [Quantity] END

// Canceled subscriptions
COUNTD([id])

// Churned MRR
SUM([Monthly value])

// Avg months before canceling
AVG(DATEDIFF('month', [Created (UTC)], [Ended At (UTC)]))

In Tableau the churn view shows a Null row for subscriptions that haven't been canceled; exclude it. The box above leaves it out.

The equivalent SQL

MRR now

WITH subs AS (
  SELECT *, CASE "Interval" WHEN 'year' THEN "Amount" * "Quantity" / 12
                       WHEN 'week' THEN "Amount" * "Quantity" * 52 / 12
                       WHEN 'day' THEN "Amount" * "Quantity" * 365 / 12
                       ELSE "Amount" * "Quantity" END AS monthly_value,
         "Status" IN ('active', 'past_due') AS in_mrr
  FROM read_csv('stripe-subscriptions.csv')
)
SELECT SUM(monthly_value) FILTER (WHERE in_mrr) AS mrr,
       SUM(monthly_value) FILTER (WHERE in_mrr) * 12 AS arr,
       COUNT(DISTINCT "Customer ID") FILTER (WHERE in_mrr) AS paying_customers,
       SUM(monthly_value) FILTER (WHERE in_mrr) / COUNT(DISTINCT "Customer ID") FILTER (WHERE in_mrr) AS mrr_per_customer
FROM subs;

MRR by product

WITH subs AS (
  SELECT *, CASE "Interval" WHEN 'year' THEN "Amount" * "Quantity" / 12
                       WHEN 'week' THEN "Amount" * "Quantity" * 52 / 12
                       WHEN 'day' THEN "Amount" * "Quantity" * 365 / 12
                       ELSE "Amount" * "Quantity" END AS monthly_value,
         "Status" IN ('active', 'past_due') AS in_mrr
  FROM read_csv('stripe-subscriptions.csv')
)
SELECT "Product",
       COUNT(DISTINCT id) FILTER (WHERE in_mrr) AS subscriptions_in_mrr,
       COALESCE(SUM(monthly_value) FILTER (WHERE in_mrr), 0) AS mrr,
       COALESCE(SUM(monthly_value) FILTER (WHERE in_mrr), 0) / (SELECT SUM(monthly_value) FROM subs WHERE in_mrr) AS share_of_mrr
FROM subs
GROUP BY "Product"
ORDER BY mrr DESC;

New MRR by start month, and how much is still in MRR

WITH subs AS (
  SELECT *, CASE "Interval" WHEN 'year' THEN "Amount" * "Quantity" / 12
                       WHEN 'week' THEN "Amount" * "Quantity" * 52 / 12
                       WHEN 'day' THEN "Amount" * "Quantity" * 365 / 12
                       ELSE "Amount" * "Quantity" END AS monthly_value,
         "Status" IN ('active', 'past_due') AS in_mrr,
         "Status" NOT IN ('trialing', 'incomplete', 'incomplete_expired', 'paused') AS started_paying
  FROM read_csv('stripe-subscriptions.csv')
)
SELECT date_trunc('month', CAST("Created (UTC)" AS DATE)) AS started,
       COUNT(DISTINCT id) FILTER (WHERE started_paying) AS new_subscriptions,
       COALESCE(SUM(monthly_value) FILTER (WHERE started_paying), 0) AS new_mrr,
       COALESCE(SUM(monthly_value) FILTER (WHERE in_mrr), 0) AS still_in_mrr,
       COALESCE(SUM(monthly_value) FILTER (WHERE in_mrr), 0) / NULLIF(SUM(monthly_value) FILTER (WHERE started_paying), 0) AS kept
FROM subs
GROUP BY started
ORDER BY started;

Churned MRR by the month a subscription ended

WITH subs AS (
  SELECT *, CASE "Interval" WHEN 'year' THEN "Amount" * "Quantity" / 12
                       WHEN 'week' THEN "Amount" * "Quantity" * 52 / 12
                       WHEN 'day' THEN "Amount" * "Quantity" * 365 / 12
                       ELSE "Amount" * "Quantity" END AS monthly_value,
         "Status" IN ('active', 'past_due') AS in_mrr
  FROM read_csv('stripe-subscriptions.csv')
)
SELECT date_trunc('month', CAST("Ended At (UTC)" AS DATE)) AS ended,
       COUNT(DISTINCT id) AS canceled_subscriptions,
       SUM(monthly_value) AS churned_mrr,
       AVG(date_diff('month', CAST("Created (UTC)" AS DATE), CAST("Ended At (UTC)" AS DATE))) AS avg_months_before_canceling
FROM subs
WHERE "Status" = 'canceled' AND "Ended At (UTC)" IS NOT NULL
GROUP BY ended
ORDER BY ended;

Traps in Stripe exports

Stripe is a trademark of Stripe, Inc. xmetric is not affiliated with Stripe. The sample file is synthetic: made-up subscriptions using column names typical of the Dashboard's subscriptions export, statuses from Stripe's API reference, as of 2026-10-18.

Questions people ask

Why doesn't this match the MRR in Stripe's Billing overview?

Stripe's number can subtract discounts, excludes trialing items and metered prices, and uses your account's time zone for charts. This page sums list price times quantity for active and past_due subscriptions; differences usually come from coupons or from subscriptions on several prices.

Is a past_due subscription churn?

Not yet. Stripe counts it in MRR until retries run out and it becomes canceled or unpaid; then it counts as churn. To be stricter, change In MRR to Status = 'active'.

Is my Stripe data uploaded?

No. The CSV is read and calculated in this browser tab; nothing is sent anywhere.

Related: cohort retention from a Stripe payments export, monthly customer and MRR churn rate, DATEDIFF, FIXED expressions. Download the sample to see the format.