Dunning Playbooks
Failed payments are not one problem in India
Indian SaaS failed payments need classifying by mandate, UPI AutoPay, AFA, soft decline, and customer action before recovery works.
The first version of our recovery engine sent exactly one message. A payment failed, a WhatsApp went out: "Your payment didn't go through, please update your card." Clean, simple, and wrong more often than it was right. We were telling people to update a card when the real problem was an expired UPI mandate, or a ₹15,000 charge that needed re-authentication, or — embarrassingly often — a debit that hadn't actually failed at all. That one generic line taught me the lesson this whole post is about: in India, recovery starts with classification, not communication.
Because here is what goes wrong when you skip it. Classify the failure badly and you send the wrong message. Send the wrong message and you train customers to tune out everything you send after it. Once they're tuning you out, a subscription that was completely recoverable quietly slides into churn — and you never even see the moment it became unsaveable.
The decline classes that actually matter
Western dunning content explains soft vs. hard declines well, and Stripe's retry docs sensibly separate retryable failures from hard declines that need a new method. Useful as a starting point — but India needs its own working set. These are the categories a recovery engine actually has to route on:
| Class | What's really happening | Right first action |
|---|---|---|
| Hard — card | Card expired or invalid | Card-update message now. No retry will fix it. |
| Hard — mandate | e-mandate expired or rejected | Customer must re-authorise (fresh AFA). The merchant can't revive a dead mandate. |
| Soft — insufficient funds | Money wasn't there at debit time | Light reminder, retry on a sensible window; consider payday timing |
| Voluntary — payer rejected | Customer declined the UPI request | Soft, low-urgency note — intent may have changed |
| Infrastructure | Gateway/bank/issuer downtime | Do nothing yet. Queue everything until it resolves. |
| Unknown | Unmapped error | Generic "small hiccup" message; tighten the map later |
A founder in Gurugram once scrolled me through a week of failed-payment alerts in his Cashfree dashboard, fast — one customer, one invoice, one red mark — and inside a minute he was calling every last one of them "payment failures." It is a convenient phrase. It is also the exact mistake: firing one generic line — "Your payment failed, please update your card" — at all six classes above. That line only works when the card is genuinely the problem. It is actively wrong for a UPI AutoPay mandate, an eNACH debit, a revoked authorisation, or a customer who simply needs to authenticate a ₹15,000-plus charge.
The one rule that prevents most false alarms
Before any of this, there is a timing check that is specific to India, and it is the one I wish someone had told me first. Since 1 August 2025, NPCI holds UPI AutoPay executions during peak hours — 10:00–13:00 and 17:00–21:30 IST — and releases them in the non-peak windows, with one main attempt and up to three retries. A debit that looks like it failed inside a peak window may simply be queued.
So the real first question is not "which message do we send?" It is "is this even a real failure yet?" Starting a recovery sequence on a peak-window UPI event that later clears on its own is exactly how teams annoy paying customers and quietly wreck their own WhatsApp sender quality at the same time. Confirm the debit has actually failed before you waste a single thought on classifying it.
A diagnostic to run inside the company first
The recovery workflow should begin with a short internal table — not a customer email.
| Question | Why it matters |
|---|---|
| Which rail and method was used? | Card, UPI, eNACH change the next step entirely |
| Was the mandate active at debit time? | No retry fixes a broken authorisation path |
| Was this a peak-window UPI execution? | It may be queued, not failed |
| Did the charge need fresh AFA (≥ ₹15,000)? | The next action is customer approval, not a silent retry |
| Has this failed before for this customer? | A repeat pattern reads differently from a one-off |
| Was payment eventually recovered, and via which touch? | Recovery rate matters more than alert volume |
It looks like an operational checklist, but it is really a strategy document in disguise. A founder who knows the failure class can decide where to actually spend effort — better retries, cleaner mandate setup, pre-debit communication, WhatsApp reminders, pricing clarity, or simply collecting a better payment method up front. A founder who never classifies does the identical thing every single week — sends reminders, waits, shrugs, calls it churn — and never once learns which lever was the broken one.
Where SubsShield fits
SubsShield treats a failed payment as an event with context, not a single red mark. It reads the decline signals from the Razorpay or Cashfree webhook, sorts the failure into the right class, suppresses messaging during downtime and peak-window ambiguity, and only then routes the rail-appropriate next action. The recovery message gets written after the system understands what failed — never before.
So here is the test for your own setup: if you had to tag every failed payment this month by the exact next action it required, how many would honestly still fit under one generic recovery sequence?

