Monthly Recurring Revenue (MRR) is the predictable revenue your business generates from active subscriptions each month. In Stripe, MRR isn't a native metric—you have to calculate it from your subscription data. Understanding your MRR is critical for forecasting, runway, and spotting growth or contraction early.
What MRR Actually Means in Stripe
MRR measures the monthly value of all active subscriptions. But Stripe subscriptions can have different billing intervals, so you need to normalize everything to a monthly value.
Understand the distinction: MRR vs. Total Billing
MRR is the recurring portion of your revenue, not one-time charges or usage-based overages. A customer on a $100/month subscription contributes $100 to MRR, regardless of add-ons or seat changes mid-cycle. Stripe tracks this through the subscription object in your Billing dashboard.
const stripe = require('stripe')('sk_live_...');
const subscription = await stripe.subscriptions.retrieve('sub_ABC123');
console.log({
id: subscription.id,
customer: subscription.customer,
status: subscription.status,
items: subscription.items.data.map(item => ({
price: item.price.id,
amount: item.price.unit_amount,
interval: item.price.recurring.interval,
interval_count: item.price.recurring.interval_count
}))
});Convert non-monthly intervals to monthly equivalents
If a customer pays $1200 yearly, that's $100/month for MRR purposes. Stripe doesn't do this conversion for you—you do. Divide annual amounts by 12, weekly by 4.33 (weeks per month).
function getMrrFromPrice(unitAmount, interval, intervalCount) {
const monthlyAmount = unitAmount / 100;
switch (interval) {
case 'month':
return monthlyAmount * intervalCount;
case 'year':
return monthlyAmount / 12;
case 'week':
return monthlyAmount * 4.33;
case 'day':
return monthlyAmount * 30.44;
default:
return 0;
}
}
const mrrFromYearly = getMrrFromPrice(120000, 'year', 1);
console.log(mrrFromYearly); // 100active. Stripe shows this in the current_period_end field.Calculate Total MRR from Your Active Subscriptions
To get your full MRR, sum the monthly values of all active subscriptions. Stripe's API makes this straightforward with status filtering.
List all active subscriptions with pagination
Use the List Subscriptions API endpoint with status: 'active' filter. This returns paginated results (100 max per page), so handle pagination if you have thousands of customers.
const stripe = require('stripe')('sk_live_...');
async function getAllActiveSubscriptions() {
let allSubscriptions = [];
let hasMore = true;
let startingAfter = null;
while (hasMore) {
const subs = await stripe.subscriptions.list({
status: 'active',
limit: 100,
starting_after: startingAfter
});
allSubscriptions = allSubscriptions.concat(subs.data);
hasMore = subs.has_more;
if (hasMore) {
startingAfter = subs.data[subs.data.length - 1].id;
}
}
return allSubscriptions;
}Calculate total MRR by summing all active items
Loop through each subscription and each line item (price). Convert to monthly equivalent and sum. Subscriptions can have multiple items, so iterate all of them.
function calculateTotalMrr(subscriptions) {
let totalMrr = 0;
for (const sub of subscriptions) {
for (const item of sub.items.data) {
const unitAmount = item.price.unit_amount || 0;
const interval = item.price.recurring?.interval || 'month';
const intervalCount = item.price.recurring?.interval_count || 1;
let monthlyValue = unitAmount / 100;
if (interval === 'year') {
monthlyValue /= 12;
} else if (interval === 'week') {
monthlyValue *= 4.33;
}
totalMrr += monthlyValue;
}
}
return Math.round(totalMrr * 100) / 100;
}
const subs = await getAllActiveSubscriptions();
const mrr = calculateTotalMrr(subs);
console.log(`Current MRR: $${mrr.toFixed(2)}`);customer.subscription.created, updated, deleted) so you recalculate only when something changes instead of fetching all subscriptions.Track MRR Changes Through Webhooks
Knowing your current MRR matters less than knowing how it's changing—churn, expansion, new customers. Webhooks let you capture these events in real-time.
Set up webhooks in Stripe Dashboard
Go to Developers > Webhooks and add an endpoint. Choose these events: customer.subscription.created, customer.subscription.updated, customer.subscription.deleted. Stripe sends POST requests to your endpoint URL whenever these events occur.
Handle webhook events to calculate MRR impact
Validate the webhook signature, parse the event, and log the MRR change. created increases MRR, updated might increase or decrease it (upgrade/downgrade), deleted decreases MRR. Use event data to avoid re-querying all subscriptions.
const express = require('express');
const app = express();
const stripe = require('stripe')('sk_live_...');
app.post('/webhooks/stripe', express.raw({type: 'application/json'}), async (req, res) => {
const sig = req.headers['stripe-signature'];
const endpointSecret = 'whsec_...';
try {
const event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
if (event.type === 'customer.subscription.created') {
const sub = event.data.object;
const mrrChange = calculateTotalMrr([sub]);
console.log(`New subscription +$${mrrChange} MRR`);
}
if (event.type === 'customer.subscription.updated') {
const sub = event.data.object;
console.log(`Updated subscription: ${sub.id}`);
}
if (event.type === 'customer.subscription.deleted') {
const sub = event.data.object;
const mrrLoss = calculateTotalMrr([sub]);
console.log(`Cancelled subscription -$${mrrLoss} MRR`);
}
res.json({received: true});
} catch (err) {
res.status(400).send(`Webhook Error: ${err.message}`);
}
});Common Pitfalls
- Forgetting to normalize different billing intervals—annual plans will inflate or distort your MRR if you don't convert to monthly.
- Including trial subscriptions or cancelled subscriptions—only count status
active. - Counting one-time charges or metered usage as MRR—they're revenue, but not recurring.
- Not accounting for paused subscriptions—
pause_atis Stripe's way of keeping a subscription alive but inactive; don't count paused revenue in MRR.
Wrapping Up
MRR is the foundation of subscription metrics. Stripe gives you the data through subscriptions.list() and webhooks, but you do the calculation. Calculate weekly, segment by plan, and track trends over time. If you want to track MRR automatically across Stripe and other tools with dashboards and cohort analysis, Product Analyst can help.