MishaBook a demo

Aug 14, 2026

Subscription Billing Decline Codes Operators Must Know

A decline code is a machine - readable response from a payment processor (Stripe, PayPal, Square) indicating why a transaction was rejected. Codes map to root causes: insufficient funds, expired card, fraud detection, processor unavailability, or issuer restrictions. Retry logic must vary by code.

Why Decline Codes Matter for Subscription Retention

Subscription churn from failed payments is often recoverable. A customer with an expired card or insufficient funds today may have both tomorrow. But operators who treat all declines identically—either retrying blindly or abandoning immediately—leave revenue on the table.

Decline codes are the signal. They tell you whether the failure is temporary (retry in 3 days) or permanent (ask the customer to update their card now). Mapping codes to retry windows and escalation paths reduces involuntary churn by 10 - 25% depending on customer cohort and payment mix.

Core Decline Code Categories

Payment processors group decline codes into families. Stripe uses a standard taxonomy; other processors (PayPal, Square, Adyen) map to similar logic. The key categories are:

  • Card - related (expired, invalid number, lost/stolen) - customer action required
  • Insufficient funds - temporary; retry after 3 - 5 days
  • Issuer unavailable - processor or bank timeout; retry after 1 - 2 hours
  • Fraud or security block - issuer flagged transaction; may require customer verification
  • Hard declines (do not retry) - invalid account, revoked card, or regulatory block

Stripe Decline Code Reference and Retry Rules

Stripe's decline codes are the industry standard for DTC operators. Below are the most common codes and recommended retry windows:

  • card_declined (generic) - Retry after 3 days. Often temporary.
  • expired_card - Do not retry automatically. Escalate to customer immediately.
  • insufficient_funds - Retry after 4 - 5 days. Customer may have pending deposits.
  • lost_card, stolen_card - Do not retry. Card issuer flagged it.
  • processing_error - Retry after 1 - 2 hours. Processor or bank was temporarily unavailable.
  • rate_limit - Retry after 30 minutes. Stripe rate limit hit; not customer fault.
  • authentication_required - Retry after customer completes 3D Secure or SCA challenge.
  • issuer_unavailable - Retry after 2 - 4 hours. Bank was down.
  • card_not_supported - Do not retry. Card type or issuer not accepted by merchant.
  • fraudulent - Do not retry. Issuer suspects fraud; customer must contact bank or update card.

Building a Retry Schedule

A retry schedule maps decline codes to timing and escalation. The formula balances recovery (more retries = higher recovery rate) against customer friction (too many failed charges = churn).

Standard retry schedule for subscription billing:

  • Attempt 1: Initial charge on billing date
  • Attempt 2: +3 days (if code is temporary: insufficient_funds, processing_error, issuer_unavailable)
  • Attempt 3: +5 days (if code still temporary)
  • Attempt 4: +7 days (final retry before dunning or cancellation)
  • Escalate to customer after Attempt 2 if code is card_declined (generic) or authentication_required
  • Hard stop (no retry) for expired_card, lost_card, stolen_card, fraudulent, card_not_supported

Dunning and Escalation Triggers

Dunning is the process of notifying and prompting a customer to update their payment method. Timing and tone matter. Escalate to dunning (email, SMS, in - app notification) based on code and attempt count:

After Attempt 1 failure with card_declined or insufficient_funds: Send soft reminder email ("We had trouble charging your card. No action needed yet.").

After Attempt 2 failure: Send urgent email + SMS. Ask customer to update card. Offer 24 - 48 hour grace period.

After Attempt 3 failure: Suspend access or flag for manual review. Do not charge again without explicit customer action.

For hard declines (expired_card, fraudulent): Escalate immediately after Attempt 1. Do not retry.

Monitoring and Alerting

Operators should track decline codes in real time to spot trends and adjust retry logic. Key metrics:

Decline rate by code: If insufficient_funds declines spike, it may signal economic downturn or seasonal cash flow issues in your customer base.

Recovery rate by code: Measure what % of Attempt 2 and Attempt 3 charges succeed. If recovery is < 5%, shorten the retry window or escalate sooner.

Time to escalation: How long between Attempt 1 and customer contact? Faster escalation (within 24 hours) yields higher recovery rates.

Churn rate post - decline: Track how many customers cancel after a failed charge. If > 30% of failed - charge customers churn, dunning messaging or grace periods may need adjustment.

Processor - Specific Variations

PayPal, Square, and Adyen use different code taxonomies. Map them to Stripe's logic for consistency:

PayPal: "10486" (card expired) maps to hard decline. "10001" (insufficient funds) maps to temporary retry.

Square: "CARD_EXPIRED" is hard decline. "CARD_DECLINED" is temporary.

Adyen: "Expired Card" is hard decline. "Insufficient Funds" is temporary.

Best practice: Standardize all processor codes to a single internal taxonomy (Stripe's is most portable) and build retry logic once.

Questions

FAQ

Should we retry all declines or only certain codes?

Retry only temporary codes (insufficient_funds, processing_error, issuer_unavailable, card_declined generic). Hard declines (expired_card, lost_card, fraudulent, card_not_supported) require customer action and should not be retried automatically. Retrying hard declines wastes processor fees and frustrates customers.

How many times should we retry before giving up?

Standard is 3 - 4 attempts over 7 - 10 days for temporary codes. After Attempt 2, escalate to the customer via email or SMS. If Attempt 4 fails, suspend service or flag for manual review. Retrying beyond 4 times yields minimal recovery and signals poor customer experience.

What's the difference between a decline and a chargeback?

A decline is a real - time rejection during the transaction. A chargeback is a dispute filed by the customer or issuer after the charge succeeds, requesting a refund. Declines are preventable via retry logic; chargebacks are disputes that require evidence and manual resolution.

Can we use decline codes to predict churn?

Yes. Customers with hard declines (expired_card, fraudulent) have 40 - 60% higher churn risk. Customers with temporary declines (insufficient_funds) have 10 - 20% higher churn. Use this to segment dunning messaging: hard - decline customers need urgent card update prompts; temporary - decline customers can receive softer reminders.

Want this on your account?

Thirty minutes. Bring the number that keeps you up.

More from the blog