← Back to blog

Why your Stripe MRR is wrong — and Stripe will never tell you

September 7, 2026

At some point you pulled up the MRR number in your Stripe dashboard, quoted it in a board deck, an investor update, or a Slack message to your co-founder, and moved on with your day. Most of the time that number is close enough. Some of the time it is quietly, structurally wrong — not because of a bug in Stripe, but because “monthly recurring revenue” is a modeling decision, and Stripe’s default model makes several choices that don’t match how most businesses actually think about revenue. None of these show up as an error. All of them look, from inside the dashboard, exactly like a correct number.

This isn’t a criticism of Stripe’s reporting — it’s a genuinely hard problem to solve generically for every business model on the platform. But if you’ve ever looked at the number and thought “that doesn’t look right” and then talked yourself out of the feeling, this is the list of specific, checkable reasons you might have been correct the first time.

1. Annual plans get squashed into a single month, then vanish for eleven

Stripe’s MRR calculation recognizes an annual subscription’s value in the month it renews, not spread evenly across the year. A customer paying $1,200/year shows up as a $1,200 spike in MRR the month they pay, then contributes roughly nothing for the following eleven months. If your business has a meaningful mix of monthly and annual plans, your MRR chart isn’t a smooth line reflecting steady recurring revenue — it’s a series of spikes that happen to land wherever your annual renewals land. A month with three annual renewals looks like explosive growth. The following month, with none, looks like a cliff. Neither is real; both are artifacts of when the calendar happened to place a renewal.

2. “Past due” still counts as active revenue

When a renewal payment fails, Stripe doesn’t immediately drop the subscription — it moves to past_due and enters your dunning retry schedule, which can run anywhere from a few days to several weeks depending on your settings. Stripe’s MRR figure, by default, still counts a past_due subscription as contributing revenue, because technically it hasn’t been canceled. You can be carrying weeks of MRR from customers whose card has been declining since the first retry attempt, reporting it as healthy revenue the entire time, with the actual cash never landing in your account.

3. Coupons and discounts distort the number in whichever direction hurts you

A subscription with a 50%-off coupon applied is either counted at full price (overstating what you actually collect) or at the discounted price if Stripe correctly applies the coupon to the reported figure — and which one happens depends on coupon type, duration, and whether it’s a percentage or fixed amount off, in ways that aren’t always obvious from the dashboard alone. Run a seasonal promotion, a lifetime deal, or founder-friend discounts, and your MRR chart can either spike (if discounts are undercounted) or dip (if they’re overcounted) in a way that has nothing to do with actual customer growth.

4. Multi-currency conversion happens at report time, not payment time

If you charge in multiple currencies, Stripe converts everything to your reporting currency using a current exchange rate for the summary figure — not the rate that was actually in effect when each customer paid. A batch of EUR or GBP subscriptions can make your MRR appear to grow or shrink between one dashboard refresh and the next with zero customer activity, purely because the exchange rate moved. If you’re presenting MRR trend data to anyone who’s going to make a decision based on the slope of the line, an unannounced FX-driven wobble is exactly the kind of thing that triggers a confused, wrong conclusion.

5. Plan changes mid-cycle create proration entries that look like separate revenue events

A customer upgrading from a $29 to $99 plan halfway through their billing cycle generates a prorated invoice item for the difference — a real, correct charge. But depending on how your reporting aggregates invoice line items versus subscription-level MRR, that proration can either get double counted alongside the new plan’s full value, or dropped entirely if your calculation only looks at the subscription’s current price and misses the one-time catch-up charge. Neither failure mode is rare once a product has more than one or two pricing tiers and any meaningful rate of customers moving between them.

Two-minute check: Pick any single month from three months ago. Sum every successful invoice.payment_succeeded event for that month directly from Stripe’s own event log or the Payments report, in whatever currency they actually settled in. Compare that number — cash that actually arrived — to what your MRR dashboard reported for the same period. A gap of a few percent is normal rounding. A gap in the double digits means one or more of the five causes above is live in your account right now.

Why this is worse than a reporting inconvenience

A wrong MRR number doesn’t just make a slide look slightly off. It’s the input to decisions that compound: how much runway you think you have, what growth rate you tell investors, whether a marketing channel gets more budget because it appears to be driving revenue it isn’t, whether you raise a round on a trajectory that a careful diligence process will eventually reprice downward once someone reconciles the number against actual bank deposits. The failure mode isn’t a single bad month — it’s a persistent, structural bias that makes every trend line you look at slightly (or significantly) misleading in a consistent direction, which is exactly the kind of error that’s hardest to catch by eyeballing a chart, because a consistently biased number still looks smooth and trustworthy.

What actually fixes it

A number you can trust is worth building once

None of the five causes above are edge cases — they’re default Stripe behavior that every business on the platform inherits the moment they have more than a single flat monthly plan, any failed payments, or any customers outside your home currency. Which, in practice, is almost every SaaS company past its first few months. The fix isn’t switching platforms or fighting Stripe — it’s treating the subscription and invoice data as the source of truth and building your own recognition logic on top of it, once, instead of re-trusting a dashboard number that was never built to model your specific business.

What we built this for

Revenue reporting is only half the problem — the other half is access. I built Venwai after running into the access side of this same gap: Stripe says a customer is paying, but the app never granted them access (see this one), or a subscription quietly stops being paid without the delete event ever firing (see this one). Venwai connects to Stripe with a read-only key, polls a single endpoint you expose on your own app once a day, and diffs who Stripe says is paying against who your app says has access — alerting you the moment they disagree, in Slack, Discord, Telegram, or email.

Free while it’s in beta, no card required: venwai.com.