Most SaaS founders track MRR, new signups, and voluntary churn religiously. But there's a number hiding in your payment provider's dashboard that you've probably never looked at: failed payments.
On average, around 9% of subscription payments fail every month. Not because customers canceled, but because their credit card expired, hit its limit, or got flagged by the bank. These customers didn't choose to leave. They just silently disappeared from your revenue.
Whether you use Stripe, Paddle, or both, here's exactly how to find your failed payments and what to do about them.
Part 1: Checking Failed Payments in Stripe
Stripe is the most popular payment processor for SaaS, and it gives you granular access to every failed charge. Here's how to find them.
Step 1: Go to your Stripe Dashboard
Log into your Stripe account and navigate to Payments in the left sidebar. By default, you're looking at successful payments. That's the problem: you never see what's failing.
Step 2: Filter by Failed Payments
Click the Status filter at the top and select Failed. This shows every payment attempt that didn't go through.
Now look at the date range. Set it to the last 30 days and count the total amount. Compare that to your MRR. If you're like most SaaS businesses, you're looking at 5-10% of your monthly revenue sitting there, uncollected.
Step 3: Look at Stripe Decline Codes
Click on any failed payment and Stripe will show you the decline code. The most common ones are:
- card_declined: Generic decline. Could be insufficient funds, fraud detection, or bank restrictions.
- expired_card: The customer's card expired and they never updated it.
- insufficient_funds: The customer didn't have enough balance. Often temporary: they might have funds a few days later.
- authentication_required: The bank wants 3D Secure verification but the customer never completed it.
Each of these requires a different recovery strategy. An expired card needs a polite email asking the customer to update their payment method. Insufficient funds? You're better off waiting a few days and retrying silently.
Different decline codes require completely different recovery strategies
Step 4: Check Stripe's Built-in Retry Schedule
Go to Settings > Billing > Subscriptions and emails > Manage failed payments. Here you'll see Stripe's Smart Retries configuration. By default, Stripe will retry failed payments using their own schedule.
The problem? Stripe's retry logic is generic. It doesn't optimize based on the specific decline reason, and the retry timing isn't tailored to maximize recovery. More on that in our post about why Stripe's default retries aren't enough.
Step 5: Check the Invoices View
For subscription businesses, the Invoices section gives a cleaner picture. Go to Billing > Invoices and filter by Status: Past due. This shows subscriptions where the latest invoice hasn't been paid - these are your at-risk customers.
Part 2: Checking Failed Payments in Paddle
Paddle handles billing differently from Stripe. As a Merchant of Record, Paddle owns the customer relationship at the payment level, which means failed payment data lives in a different place and uses different terminology.
Step 1: Go to Paddle Transactions
Log into your Paddle dashboard and navigate to Transactions. This is the equivalent of Stripe's Payments view.
Step 2: Filter by Past Due Subscriptions
In the Subscriptions section, filter by status: Past due. These are subscriptions where Paddle attempted to charge the customer but the payment failed. Unlike Stripe where you see individual charge attempts, Paddle groups everything at the subscription level.
You can also check Transactions and filter by status to see individual failed transaction attempts and their error details.
Step 3: Understand Paddle's Failure Reasons
Paddle's transaction payment failures use a different classification system than Stripe. The main failure categories are:
- declined: The payment method was declined by the processor or bank.
- expired: The card on file has expired.
- insufficient_funds: Not enough balance to complete the charge.
- cancelled: The transaction was cancelled before completion.
Paddle provides less granularity than Stripe in decline codes because, as a Merchant of Record, they abstract away some of the payment complexity. This is a trade-off: less operational burden for you, but also less visibility into the specific bank-level decline reason.
Step 4: Check Paddle's Retry Behavior
Paddle automatically retries failed subscription payments. You can configure retry behavior in Subscriptions > Settings. Paddle's dunning process allows you to set:
- How many times to retry before canceling
- The interval between retry attempts
- Whether to send email notifications to customers
Paddle's built-in dunning is more configurable than Stripe's default Smart Retries, but it still lacks decline-specific retry logic and multi-channel outreach (WhatsApp, SMS, in-app banners).
Step 5: Use Paddle's API for Deeper Visibility
If you want programmatic access to failed payment data, Paddle's Transactions API lets you list all transactions filtered by status. You can also subscribe to the transaction.payment_failed webhook event to get real-time notifications when a payment fails.
Stripe vs Paddle: Failed Payment Comparison
| Feature | Stripe | Paddle |
|---|---|---|
| Where to check | Payments > Filter by Failed | Subscriptions > Past Due |
| Decline code granularity | 50+ specific codes | Simplified categories |
| Built-in retries | Smart Retries (ML-based) | Configurable retry schedule |
| Default recovery rate | ~38% | ~35-40% |
| Dunning emails | Basic, single template | Configurable, but basic |
| API access | Full charge/invoice API | Transactions API + webhooks |
| Multi-channel recovery | Email only | Email only |
Both providers leave significant revenue on the table with their default recovery tools. Neither offers SMS, WhatsApp, in-app banners, or decline-specific retry strategies out of the box.
What to Do With This Data
Now that you can see your failed payments, here's the math:
- Your MRR: Let's say $10,000
- Failed payment rate: ~9% = $900/month
- Default recovery rate: ~38% = $342 recovered
- What's left on the table: $558/month = $6,696/year
That's real money walking out the door every month. And most founders don't know it's happening until they check.
Your Options
You have three choices:
- Do nothing. Keep losing 5-10% of MRR and let your provider's basic retries handle it (they'll recover about a third).
- Handle it manually. Check failed payments weekly, email customers yourself, retry manually. Works at small scale but doesn't scale.
- Automate recovery. Use a dunning tool that works with both Stripe and Paddle, retries intelligently based on the failure reason, and reaches customers through channels they actually check - email, SMS, WhatsApp, or in-app payment banners embedded on your site. Tools with checkout recovery catch abandoned sessions, cancellation flows retain at-risk subscribers, win-back campaigns re-engage churned customers, and Apple Pay / Google Pay make mobile payment updates frictionless.
Whatever you choose, the first step is the same: go look at your failed payments right now. The number might surprise you.