How failed payments quietly erode your MRR
Last updated: November 8, 2026
SoleOS: One dashboard for revenue, traffic and live signals across every app, game and website you run. Start 7-day trial →
From the SoleOS answers series — written about our own product space; grounded in published definitions and documented behavior, never invented numbers.
Failed payments shrink your real, collectible MRR immediately, but most tools still count that subscriber as active until the dunning window closes — usually 3 to 21 days depending on the processor's retry schedule. During that window your dashboard MRR is overstated, and if you don't track involuntary churn separately from voluntary cancellations, you'll misread a billing problem as a product problem (or vice versa).
What actually happens when a card fails
A failed renewal charge doesn't mean the customer quit. It usually means one of a few boring things happened: the card expired, the bank flagged the charge as suspicious, there wasn't enough balance, or the card network did a routine re-issue. Stripe and RevenueCat both know this, which is why they don't cancel the subscription on the first failure — they enter a retry sequence (often called "smart retries" or dunning) that tries the charge again over several days, sometimes alongside an email asking the customer to update their card.
Until that sequence ends in either a successful charge or a final cancellation, the subscription sits in a limbo state: past_due in Stripe, or a grace-period/billing-issue state in RevenueCat for mobile subscriptions. Some tools still count past_due subscribers as active MRR contributors. Some don't. This inconsistency is exactly why your dashboard number and your bank balance can disagree for a week or two, similar to the mismatches described in tracking Stripe and RevenueCat together.
Three ways dunning distorts your MRR
1. MRR looks higher than what you'll actually collect. If ten subscribers go past_due on the 1st and your dashboard still counts them through day 14 of retries, you're carrying phantom revenue for two weeks. On a small portfolio this can be a few hundred dollars that quietly disappears once retries exhaust.
2. Churn gets misattributed to the wrong week. A customer who canceled because of a failed card typically shows up as "canceled" on the day dunning finally gives up — not the day the card actually failed. If you're looking at week-over-week churn, the spike lands on the wrong week, and you end up investigating a pricing change or feature release that had nothing to do with it.
3. Involuntary churn hides inside voluntary churn. This is the costly one. Voluntary churn (someone actively canceling) tells you something about product or pricing. Involuntary churn (a card just stopped working) tells you something about your billing retry logic, card update emails, or whether you're using Stripe's/RevenueCat's smart retry features at all. Lump them together and you'll chase the wrong fix — rewriting your onboarding flow when the real leak is that you're not sending card-expiration reminders.
What to measure instead of trusting the top-line MRR number
Pull these apart, even with a simple spreadsheet, before layering on tooling:
- Active MRR — subscriptions currently in good standing and billing successfully.
- At-risk MRR — subscriptions currently in a
past_due/grace-period/billing-issue state, still being retried. - Involuntary churned MRR — subscriptions that ended because retries exhausted, not because the customer canceled.
- Voluntary churned MRR — subscriptions explicitly canceled by the customer.
Most dashboards collapse all four into one "MRR" line and one "churn" line. That's fine for a single product with low volume. It gets misleading fast once you're running several products with different billing providers — one app on Stripe web checkout, another on RevenueCat for mobile IAP — because each platform's definition of "past due" and its retry windows are different lengths. See the metrics dictionary for how these states get normalized if you want exact formulas rather than taking a tool's word for it.
The practical fix: shorten the window, don't just track it
Tracking at-risk MRR is diagnostic, not curative. The actual lever is reducing how long subscribers sit in the gray zone and how many of them come out the other side canceled instead of recovered:
- Turn on card-expiration update prompts (Stripe's customer portal and RevenueCat's billing issue flows both support this) so customers fix the card before the first failed charge, not after.
- Use the processor's built-in smart retry schedule instead of retrying on a fixed interval you wrote yourself — the built-in versions are tuned against issuer-level patterns you don't have visibility into.
- Set a clear cutoff for how long "past due" is allowed to run before you treat it as churned in your own internal number, even if the processor's official cancellation hasn't fired yet. A week of generous grace is reasonable; a month inflates your reported MRR for no good reason.
None of this requires new software — it requires looking at past_due and billing-issue states as a distinct category instead of ignoring them until they resolve themselves.
Where portfolio tracking makes this harder, not easier
Running one product, you can eyeball the Stripe dashboard and know within a day if something's off. Running eight or ten products across web and mobile, each with its own retry window and its own definition of "at risk," you lose that intuition fast. A few apps on annual plans barely notice dunning; a few on monthly plans with a lot of free-trial-to-paid conversion will bleed from it constantly, and the aggregate MRR number across your whole portfolio can mask which specific product has a billing-health problem.
This is the kind of thing SoleOS was built to surface — this post comes from SoleOS, so take that as disclosure, not neutral analysis. It pulls Stripe and RevenueCat data per project and normalizes churn so you can see which product's MRR dip is a real cancellation wave versus a batch of expired cards. That said, if you run one or two products on a single billing provider, you genuinely don't need a portfolio tool for this — Stripe's own dashboard plus a monthly glance at the past_due filter will tell you most of what matters. You only start needing something like SoleOS pricing once reconciling four or five dashboards by hand starts eating an afternoon a month. You can also see how this plays out with real numbers from a 10-app portfolio if you want context before deciding.
Frequently asked questions
Does a past_due subscriber count as churned?
Not immediately. Most processors keep the subscription active while retrying the charge, which can take anywhere from a few days to three weeks depending on configuration. It only becomes a cancellation once the retry schedule exhausts without a successful charge. Until then, it's more accurate to call it "at-risk MRR" than active or churned.
How long should I let dunning retries run before giving up on a subscriber?
There's no universal number — it depends on your price point and how often customers update expired cards on their own. Rather than picking a number from a benchmark post, watch your own recovery rate: what percentage of past_due subscriptions eventually resolve successfully within your current retry window. If recovery past day 10 is near zero for your product, extending retries further mostly just inflates your reported MRR without recovering real revenue.
Is involuntary churn worth tracking separately if my portfolio is small?
Yes, even at low volume, because the fix is completely different from voluntary churn. A product with high involuntary churn needs better card-update prompts and retry logic; a product with high voluntary churn needs a pricing or product conversation. Mixing the two into one churn number means you can't tell which conversation to have.
Do annual subscribers get affected by dunning too?
Yes, though less frequently since there are fewer renewal events per year. The impact per failure is larger, though — losing one annual renewal is a bigger single hit to MRR than losing one monthly renewal, so it's worth watching even if the volume is lower.
Can I see at-risk MRR separately across multiple products automatically?
If you're using Stripe and RevenueCat, both expose billing-issue/past-due states through their dashboards and APIs, so you can build this view yourself with enough SQL or spreadsheet time. Tools that connect to both — see what SoleOS connects to for how that access works — can save the manual reconciliation once you're tracking more than two or three products at once. </contentMarkdown> <tags">["dunning","mrr","churn","reconciliation","stripe"]</tags>