Stripe doesn't have a built-in MRR metric, so you need to calculate it yourself from subscription data. If you're running a subscription business, knowing your real MRR—not just total subscription value—is critical for spotting churn, growth, and pricing problems. We'll walk through using Stripe's dashboard reports and the API to track MRR accurately.
Finding MRR in the Stripe Dashboard
Stripe's Reports feature gives you a starting point, but you'll need to understand what you're looking at and what's missing.
Open the Subscriptions report
Log into your Stripe dashboard and navigate to Billing > Reports. Click Subscriptions. This shows your subscription count and status breakdown, but not MRR directly. You'll see Active, Trialing, Past Due, and Canceled subscriptions. To get to revenue, you need to either export this data or calculate it from the API.
// Dashboard navigation: Billing > Reports > Subscriptions
// Shows subscription count by status but not MRR
// Use API for real-time MRR calculation insteadExport snapshot data if you need historical context
The Reports page has an Export button for a CSV snapshot. This is useful for one-off analysis, but for real-time MRR monitoring, use the API instead.
// Manual export provides a snapshot (not live)
// Includes: subscription ID, customer, status, current_period_start, amount
// For automation and real-time tracking, query the Stripe API directlyCalculate MRR Using the Stripe API
Query subscriptions directly and normalize billing intervals to get an accurate monthly revenue number.
Fetch all active subscriptions with line items
Use stripe.subscriptions.list() to pull every active subscription. Expand the items array to get pricing details. Filter by status: 'active' to exclude paused, canceled, or trialing subscriptions (unless you account for those separately).
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const subscriptions = await stripe.subscriptions.list({
status: 'active',
limit: 100,
expand: ['data.items'],
});
console.log(`Found ${subscriptions.data.length} active subscriptions`);
subscriptions.data.forEach((sub) => {
console.log(`Subscription ${sub.id}: ${sub.items.data.length} items`);
});Normalize billing intervals to monthly amounts
Each subscription item has a price with a recurring.interval field—month, year, week, or day. For MRR, convert everything to a monthly equivalent. A $120/year charge is $10/month; a $3.50/week charge is ~$15.17/month.
function calculateMrr(subscriptions) {
let totalMrr = 0;
subscriptions.data.forEach((sub) => {
sub.items.data.forEach((item) => {
const { recurring, unit_amount } = item.price;
if (!recurring) return; // Skip one-time charges
let monthlyAmount = unit_amount;
if (recurring.interval === 'year') {
monthlyAmount = unit_amount / 12;
} else if (recurring.interval === 'week') {
monthlyAmount = (unit_amount * 52) / 12;
} else if (recurring.interval === 'day') {
monthlyAmount = unit_amount * 30;
}
// 'month' interval is already monthly
totalMrr += monthlyAmount;
});
});
return Math.round(totalMrr) / 100; // Return in dollars
}
const mrr = calculateMrr(subscriptions);
console.log(`Total MRR: $${mrr.toFixed(2)}`);
}Exclude subscriptions with cancel dates or paused status
Filter out subscriptions where cancel_at is set (scheduled cancellations) or status is paused. These inflate your MRR number and hide real churn. Be deliberate about what counts toward your revenue baseline.
const activeOnly = subscriptions.data.filter((sub) => {
// Exclude if scheduled to cancel
if (sub.cancel_at) return false;
// Exclude if paused
if (sub.status === 'paused') return false;
return true;
});
const mrrExclusions = calculateMrr({ data: activeOnly });
console.log(`MRR (excluding paused/canceled): $${mrrExclusions.toFixed(2)}`);
console.log(`Subscriptions counted: ${activeOnly.length}`);
}starting_after parameter with the last subscription ID to fetch the next page.Monitor MRR Changes in Real-Time with Webhooks
Listen for subscription lifecycle events and recalculate MRR each time. This gives you visibility into churn, upgrades, and expansion revenue.
Set up a webhook endpoint for subscription events
Configure a webhook in Developers > Webhooks to listen for customer.subscription.created, customer.subscription.updated, and customer.subscription.deleted. Stripe will POST events to your endpoint. Verify the signature using stripe.webhooks.constructEvent().
const express = require('express');
const app = express();
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
app.post('/webhooks/stripe', express.raw({type: 'application/json'}), (req, res) => {
const sig = req.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(
req.body,
sig,
process.env.STRIPE_WEBHOOK_SECRET
);
} catch (err) {
console.error(`Webhook error: ${err.message}`);
return res.sendStatus(400);
}
const subscriptionEvents = [
'customer.subscription.created',
'customer.subscription.updated',
'customer.subscription.deleted',
];
if (subscriptionEvents.includes(event.type)) {
console.log(`Received ${event.type} for subscription ${event.data.object.id}`);
// Recalculate MRR here
}
res.sendStatus(200);
});
app.listen(3000);
}Calculate and log MRR deltas after each event
When a subscription event fires, query the API for updated subscriptions and recalculate total MRR. Compare it to the previous value to get a delta. Log the change, the event type, and the timestamp so you can track MRR trends over days and weeks.
async function recordMrrChange(eventType, previousMrr) {
const subscriptions = await stripe.subscriptions.list({
status: 'active',
limit: 100,
expand: ['data.items'],
});
const currentMrr = calculateMrr(subscriptions);
const delta = currentMrr - previousMrr;
const deltaPercentage = ((delta / previousMrr) * 100).toFixed(2);
const record = {
timestamp: new Date().toISOString(),
event: eventType,
previous_mrr: previousMrr,
current_mrr: currentMrr,
delta_dollars: delta.toFixed(2),
delta_percent: deltaPercentage,
};
console.log(`${eventType}: MRR $${currentMrr.toFixed(2)} (${deltaPercentage}% change)`);
// Log to your database, analytics tool, or monitoring dashboard
await logToDatabase(record);
return currentMrr;
}
}Common Pitfalls
- Forgetting to normalize billing intervals—if half your customers pay annually and you don't divide by 12, your MRR will be 5–10x higher than reality.
- Counting paused or cancel-scheduled subscriptions—they artificially inflate MRR and mask real churn. Always filter these out.
- Including trial subscriptions in MRR—trials don't generate revenue yet. Decide upfront if trials should be counted separately or excluded.
- Ignoring prorations on mid-cycle upgrades and downgrades—Stripe creates invoice line items for the difference, and if you're not careful, you'll double-count changes.
Wrapping Up
MRR is the heartbeat of subscription businesses, and Stripe gives you all the data you need—it just doesn't hand you a pre-calculated number. By querying subscriptions via the API, normalizing billing intervals, and monitoring changes with webhooks, you get a real-time, accurate picture of recurring revenue. If you want to track this automatically across tools, Product Analyst can help.