6 min read

What Is ARR in Stripe

Your SaaS revenue looks good, but does it actually tell the story? If you're running subscriptions through Stripe, you probably need to know your Annual Recurring Revenue (ARR) — the lifeblood metric every subscription business tracks. ARR shows you predictable revenue for the next 12 months, giving you real visibility into growth.

What ARR Is and Why Stripe Makes It Possible

ARR is the total revenue you can expect from all active subscriptions over a year. Stripe stores all your subscription data in a queryable format, which means you have everything you need to calculate it yourself.

Understand ARR as a sum of annualized subscription amounts

ARR takes every active subscription your customers pay, multiplies it by how often they pay it (monthly becomes ×12), and adds them together. Unlike other revenue metrics, ARR only counts recurring charges — one-time purchases don't factor in. In Stripe, all subscription details live in the Subscriptions section of the Dashboard, but the real power comes from the API.

javascript
// ARR is the sum of all active subscription values annualized
// If a customer pays $100/month, that's $1,200 ARR
const stripe = require('stripe')('sk_live_...');

// Fetch all active subscriptions
const subscriptions = await stripe.subscriptions.list({
  status: 'active',
  limit: 100
});

console.log(`Found ${subscriptions.data.length} active subscriptions`);
Fetch active subscriptions from Stripe API

Know the difference between MRR and ARR

MRR (Monthly Recurring Revenue) is what you collect each month. ARR is MRR × 12. The key difference: ARR assumes your subscriptions stay active for the full year, making it a projection metric. It's useful for forecasting but doesn't account for churn. Stripe doesn't distinguish between the two — you calculate ARR yourself from the subscription data.

javascript
// Calculate MRR and ARR from a single subscription
const subscription = await stripe.subscriptions.retrieve('sub_...');
const monthlyAmount = subscription.items.data[0].price.unit_amount / 100;

const mrr = monthlyAmount;
const arr = monthlyAmount * 12;

console.log(`MRR: $${mrr}, ARR: $${arr}`);
MRR is monthly, ARR is annualized
Tip: ARR only makes sense for subscriptions with monthly or yearly billing cycles. If you have weekly subscriptions, multiply by 52 instead. Adjust your calculation to match your actual billing periods.

Calculate ARR from Your Stripe Data

Once you understand the math, getting ARR from Stripe is straightforward — query subscriptions, extract the amount from each, annualize it, and sum.

Pull all active subscriptions and their recurring amounts

Use the Stripe API to fetch subscriptions with status: 'active'. The amount you charge is in the items array under each subscription — specifically in price.unit_amount. This is the amount per billing cycle in cents, so divide by 100 to get dollars.

javascript
const stripe = require('stripe')('sk_live_...');

let arr = 0;
let hasMore = true;
let startingAfter = null;

while (hasMore) {
  const subscriptions = await stripe.subscriptions.list({
    status: 'active',
    limit: 100,
    starting_after: startingAfter
  });

  subscriptions.data.forEach(sub => {
    const monthlyAmount = sub.items.data[0].price.unit_amount / 100;
    arr += monthlyAmount * 12;
  });

  hasMore = subscriptions.has_more;
  startingAfter = subscriptions.data[subscriptions.data.length - 1]?.id;
}

console.log(`Total ARR: $${arr.toFixed(2)}`);

Handle subscriptions with multiple items or different billing cycles

If a customer has multiple line items in a single subscription (e.g., base + add-on), add each item's amount. If someone's on a yearly plan, multiply by 1 instead of 12. Check price.recurring.interval to know the billing cycle. For complex setups, build a helper function that normalizes everything to annual amounts.

javascript
function getAnnualAmount(subscriptionItems) {
  return subscriptionItems.data.reduce((total, item) => {
    const amount = item.price.unit_amount / 100;
    const interval = item.price.recurring.interval;
    const intervalsPerYear = interval === 'month' ? 12 : interval === 'year' ? 1 : 52;
    return total + (amount * intervalsPerYear);
  }, 0);
}

const subscription = await stripe.subscriptions.retrieve('sub_...');
const annualAmount = getAnnualAmount(subscription.items);

console.log(`Annual amount: $${annualAmount.toFixed(2)}`);

Account for discounts and coupons applied to subscriptions

Stripe applies discounts at the subscription level through the discount field. If a discount is active, subtract its effect from the total. For a percentage-based coupon, calculate the effective amount. Always check subscription.discount before finalizing your ARR number.

javascript
function getEffectiveMonthlyAmount(subscription) {
  const items = subscription.items.data;
  const baseAmount = items.reduce((sum, item) => sum + item.price.unit_amount, 0) / 100;
  
  if (subscription.discount) {
    const discount = subscription.discount.coupon;
    if (discount.percent_off) {
      return baseAmount * (1 - discount.percent_off / 100);
    } else if (discount.amount_off) {
      return Math.max(0, baseAmount - discount.amount_off / 100);
    }
  }
  
  return baseAmount;
}

const effectiveMonthly = getEffectiveMonthlyAmount(subscription);
const effectiveAnn = effectiveMonthly * 12;

console.log(`Effective ARR: $${effectiveAnn.toFixed(2)}`);
Watch out: Stripe's unit_amount is always in cents. Always divide by 100 before displaying or calculating. Miss this and your ARR will be 100× too high.

Track ARR Changes Over Time

A single ARR snapshot is useful, but you need to track how it changes. Stripe Events give you a clean way to monitor subscription changes and recalculate ARR when it matters.

Listen for subscription events that affect ARR

When a subscription is created, updated, or canceled, Stripe sends events: customer.subscription.created, customer.subscription.updated, and customer.subscription.deleted. These events tell you exactly when your ARR changed. Build a listener that catches these and logs the impact.

javascript
const stripe = require('stripe')('sk_live_...');

const handleWebhook = async (event) => {
  switch (event.type) {
    case 'customer.subscription.created':
    case 'customer.subscription.updated':
    case 'customer.subscription.deleted':
      console.log(`Subscription event: ${event.type}`);
      console.log(`Customer: ${event.data.object.customer}`);
      // Recalculate ARR or log the change
      break;
  }
};

app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
  const event = JSON.parse(req.body);
  handleWebhook(event);
  res.send({received: true});
});
Tip: Don't recalculate ARR on every event — that's inefficient. Instead, log subscription changes and run a full ARR calculation once a day via a scheduled job. Stripe can handle thousands of subscriptions; fetching them all repeatedly will slow you down.

Common Pitfalls

  • Forgetting to filter for status: 'active' — paused and canceled subscriptions should never count toward ARR
  • Using unit_amount without dividing by 100 — Stripe stores amounts in cents, not dollars
  • Not accounting for different billing cycles — a yearly subscription should multiply by 1, not 12
  • Ignoring discounts and coupons — an effective ARR number must subtract active discounts from the total

Wrapping Up

ARR in Stripe is your subscription data annualized and summed. It's not a built-in metric, but Stripe's API makes it simple to calculate. Pull active subscriptions, multiply by the annual frequency, and you have your ARR. 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