Definition
A failed payment occurs when a subscription renewal charge is declined by the payment gateway or the customer's bank. Common causes include expired credit cards (40-50% of failures), insufficient funds (15-20%), bank fraud blocks (10-15%), or card replacements after loss or expiry (15-20%).
Failed payments are the primary driver of involuntary churn in WooCommerce subscription businesses. Each failure has a specific decline code from the issuing bank — understanding these codes helps you optimize recovery strategy.
For example, "insufficient_funds" failures should retry just after typical payday cycles, while "card_expired" failures need updater services that automatically refresh card details from the bank.
Why It Matters for WooCommerce Stores
A single failed payment does not mean the customer wants to leave — but without automatic retry logic and clear communication, it results in a lost subscriber. For WooCommerce subscription businesses, payment failures that are not recovered within 14-21 days rarely convert back.
Every unrecovered failure directly reduces MRR. The financial scale is significant: industry data suggests 5-15% of all subscription renewals fail on the first attempt, but proper dunning recovers 50-75% of those.
So a $20K MRR business might see $1,500/month of "first-attempt failures" — recovering 60% means $900/month of saved revenue, $10,800/year of preserved MRR. Without recovery infrastructure, that money simply disappears.
How It Works
Gateway attempts charge → decline returned with a specific reason code → WPSubscription marks subscription "past due" → retry logic fires on day 1, day 3, and day 7 (or your configured schedule) → customer receives email asking to update their payment method → email contains direct link to My Account where they can update card → if all retries fail after the grace period (typically 14-21 days), the subscription is automatically cancelled. The decline reason determines optimal strategy: card expired suggests an updater service, insufficient funds suggests timing-based retry, fraud block requires customer contact, and pickup_card or stolen_card means abandon the subscription entirely.
Real-World Example
A customer's monthly $39 subscription tries to renew on March 15. Stripe returns "card_expired" — the customer's card expired in February.
WPSubscription marks the subscription past-due and sends email: "Your $39 payment failed because your card has expired. Click here to update your card." On March 16, retry attempt 1 — same failure.
On March 22, retry 2. On March 29, retry 3.
Meanwhile, customer received 3 emails. On March 26, customer clicks the link in the email, enters their new card, and the next retry on March 29 succeeds.
Subscription restored, $39 captured, customer retained — all without admin intervention.
Best Practices
- Implement 3-attempt retry schedule (day 1, day 3, day 7) — catches most recoverable failures
- Send customer notification within hours of the first failure — recovery probability drops with delay
- Use gateway account updater services for automatic expired-card recovery
- Send card-expiry warnings 30 days before known card expiration dates
- Track failure rates and recovery rates as weekly KPIs — early warning of larger issues
Common Mistakes
- No retry schedule — treating the first decline as a permanent customer decision to leave
- Not sending customer notification emails immediately after a payment failure
- Using vague email copy ("your account is at risk") instead of specific, actionable instructions
- Making it difficult to update payment details — buried account area, no direct link from email
- Treating all decline reasons identically — fraud declines need different handling than insufficient funds
In WooCommerce with WPSubscription
WPSubscription logs all payment failures with detailed status information, triggers automatic retry schedules, and sends customer-facing notification emails with direct links to update payment details — recovering a significant portion of failed payments automatically. The plugin works alongside Stripe's Smart Retries (ML-optimized retry timing) for even better recovery rates, achieving 60-75% recovery on first-attempt failures in well-configured stores.