Monthly recurring revenue (MRR) is the monthly run-rate of active subscription revenue after each price is normalized to one month. A $30 plan billed every month contributes $30. A $120 plan billed once a year contributes $10, because the yearly amount is divided by 12. One-time charges are not MRR. MRR measures the pace of recurring revenue, not the cash that landed in a calendar month.
Formula
Stripe does not store an MRR field on the Subscription object. A common calculation sums a monthly amount for each active subscription item. unit_amount is in the price's minor currency unit. For USD, divide by 100. Zero-decimal currencies do not use that divisor. quantity is the subscription item quantity.
| Billing interval | Monthly amount |
|---|---|
| Month, interval_count n | (unit_amount * quantity / minor units) / n |
| Year, interval_count n | (unit_amount * quantity / minor units) / (12 * n) |
| Week, interval_count n | (unit_amount * quantity / minor units) * 52 / 12 / n |
| Day, interval_count n | (unit_amount * quantity / minor units) * 365 / 12 / n |
Trialing subscriptions are usually left out until the first paid invoice. past_due is a policy choice: some teams keep it in MRR, and some remove it. Prices with a null unit_amount (tiered or metered) need a separate usage rule. They are not zero by definition, and they are not the list price either.
Worked example
Every figure in this example is hypothetical. It is not the public demo and not a customer account. The book has three groups of active paid subscriptions, all in USD.
| Hypothetical contracts | Normalization | MRR |
|---|---|---|
| 40 plans at $30 every month, quantity 1 | 40 * 30 | $1,200 |
| 10 plans at $120 every year, quantity 1 | 10 * (120 / 12) | $100 |
| 5 plans at $50 every month, quantity 2 | 5 * 50 * 2 | $500 |
| Total | 1,200 + 100 + 500 | $1,800 |
If the yearly plans were added as $120 instead of $10, the same book would be reported as $2,900. That number is not monthly recurring revenue. A one-time $400 setup fee collected this month would raise cash collected and would leave this $1,800 MRR unchanged.
How to compute it from Stripe
- List subscriptions with status=active so trialing subscriptions stay out. Follow Stripe auto-pagination until has_more is false.
- For each subscription item, read price.unit_amount, price.currency, price.recurring.interval, price.recurring.interval_count, and quantity.
- Convert minor units with that currency's decimal rules, multiply by quantity, then normalize the interval to one month using the table above.
- Apply percent-off and amount-off coupons that still recur. Leave duration once out. Skip prices whose unit_amount is null unless you have an explicit usage amount.
- Do not add the latest charge or invoice into this sum. Cash collected is a different report.
What Data Lighthouse shows
The signed-in overview cards are Revenue (7, 14, or 30 days), Avg daily revenue, Monthly recurring revenue, Annual recurring revenue, Revenue per visitor, Visitor conversion rate, and Visitors online. The Monthly recurring revenue card reads GET /api/datalighthouse/revenue for a signed-in Clerk user. The route lists every subscription with status active through Stripe auto-pagination, which leaves trialing subscriptions out. For each subscription item it multiplies price.unit_amount by quantity, converts that minor-unit amount for the price currency, and normalizes the recurring interval to one month. A year is divided by 12, a week is multiplied by 52/12, a day is multiplied by 365/12, and interval_count divides the result. Percent-off and amount-off coupons that still apply (duration forever, or repeating and not yet ended) are included. A coupon with duration once is left out, because it does not recur. Item coupons apply before subscription coupons. A coupon that lives only on the Stripe Customer is not included. Prices with no unit_amount, such as tiered or metered prices, are skipped. The route assumes one currency, the currency of the first priced active item, and leaves items in any other currency out of the sum. Zero-decimal currencies such as JPY are not divided by 100. The three-decimal currencies BHD, JOD, KWD, OMR, and TND are divided by 1000. The card shows that normalized total. A percent change needs a stored starting snapshot, which this route does not keep.
The public demo does not call Stripe or Postgres. Revenue, visitors, monthly recurring revenue, and annual recurring revenue are a seeded sample. ARR in the sample is the sample MRR times 12. Each day's visitors are seeded on their own, separate from that day's revenue, and the chart subtitle labels the series as sample data. Checkout for the $59 template license uses Polar after GitHub sign-in. Stripe is the optional revenue source inside the dashboard you host, through STRIPE_SECRET_KEY. If that key is missing, the revenue API returns an error and the overview says it could not load Stripe revenue.
Questions
What is monthly recurring revenue?
Monthly recurring revenue (MRR) is the monthly run-rate of active subscription revenue after each price is normalized to one month. A yearly price is divided by 12. One-time charges are not MRR, and MRR is not the cash collected in the calendar month.
How do you calculate MRR from Stripe?
Stripe does not return an MRR field. List the subscriptions you count, paginate while has_more is true, and for each item convert price.unit_amount with the currency's minor units, multiply by quantity, then divide a yearly price by 12 (and by interval_count when it is greater than 1). Skip prices with no unit_amount, such as tiered or metered prices, unless you price them from usage on purpose.
Does the Data Lighthouse template divide yearly prices by 12?
Yes. The MRR card normalizes every active subscription item to one month. A yearly price is divided by 12, a weekly price is multiplied by 52/12, and a daily price by 365/12. Quantity is included, trialing subscriptions are excluded, and the route follows Stripe auto-pagination.
Related reading
- Next.js Stripe analytics dashboard template
- Public live demo
- Template checkout
- Annual recurring revenue (ARR)
- Churn rate
- Average revenue per user (ARPU)