6 min read

How to Monitor MRR in Stripe

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.

javascript
// Dashboard navigation: Billing > Reports > Subscriptions
// Shows subscription count by status but not MRR
// Use API for real-time MRR calculation instead
Navigate to Subscriptions report in the Stripe dashboard

Export 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.

javascript
// 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 directly
Dashboard export is manual—use the API for live tracking
Watch out: Dashboard snapshots are historical. For live MRR, query the API in the next section.

Calculate 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).

javascript
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`);
});
Retrieve active subscriptions with nested line item data

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.

javascript
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)}`);
}
Normalize all billing intervals to monthly revenue

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.

javascript
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}`);
}
Filter out paused and cancel-scheduled subscriptions
Tip: Stripe's API paginates at 100 by default. If you have >100 subscriptions, use the 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().

javascript
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);
}
Verify and handle subscription events from Stripe webhooks

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.

javascript
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;
}
}
Track MRR deltas to spot trends in growth, churn, and expansion
Tip: Use ngrok or localtunnel during development to expose your local webhook endpoint to the internet and test real Stripe events before deploying.

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.

Track these metrics automatically

Product Analyst connects to your stack and surfaces the insights that matter.

Try Product Analyst — Free