DEV Community

Swipe Again for Swipe Again

Posted on

Stripe Dunning Software Is a Layer, Not a Replacement for Billing

If you maintain subscription billing, you have probably had this conversation. Churn ticked up, someone opened Stripe, pointed at the retry settings, and asked why the built-in tools were not enough. It is a fair question, and it has a useful answer: Stripe is very good at being the system that records subscriptions and attempts charges. Dunning, done well, is a different job that sits on top of that system. Treating the two as substitutes hides where recoveries are actually won and lost.

Think of the stack as an anatomy, not a feature list. Each layer has one responsibility, and most failed-payment problems come from asking one layer to do another layer's work.

Layer 1: The ledger

Stripe Billing is the ledger. It knows who subscribed, to what, on which price, and when the next invoice is due. It creates the invoice, finalizes it, and records the outcome of every attempt. That record matters. If your ledger is messy — duplicate customers, stale prices, trials that never converted cleanly — no recovery tool will save you, because it will be recovering against bad data. Keep this layer boring: one customer per account, metadata you actually maintain, and webhooks you monitor instead of assume.

Layer 2: The attempt

A charge attempt is a conversation with an issuing bank, and the bank answers with a decline code. Some answers are final, like a closed account or confirmed fraud. Some are temporary, like insufficient funds or a processor timeout. Some are instructions, like 'do not honor' paired with a request to update credentials. Developers often log these as a single boolean — paid or failed — and throw away the most valuable part: the reason. Preserve the raw decline code, the network advice, and the attempt timestamp on the invoice. Your retry strategy is only as good as the signal you keep.

Layer 3: The decision

This is the layer people usually mean by dunning, and it is a decision engine, not a cron job. Given this decline, this card type, this customer's tenure, and this time of month, what should happen next, and when? Retrying a salary-paid customer two days later is rational. Retrying a hard decline five times is not; it wastes attempts, annoys issuers, and can look like abuse. Good decisions also know when not to act through the processor at all — when the right move is asking the customer for a new card. This is where stripe dunning software that keeps working after the first retry earns its place: not by replacing the ledger, but by making better decisions on top of it.

Layer 4: The conversation with the customer

Email is part of this layer, but so are in-app banners, the timing of the first notice, and the tone. Send the first message while the problem is still fixable and the customer still remembers subscribing. Say which charge failed, for how much, and what happens next, in plain language. Do not bury the update link, do not require a full login flow if a secure, expiring link will do, and do not send four emails that all say the same thing louder. Each message should correspond to a state change — first failure, retry scheduled, card expiring, final attempt — not to a marketer's calendar.

Layer 5: The card-update surface

When a customer does click through, the page they land on decides whether the previous four layers mattered. It should show the account, the amount owed, and one clear form, prefilled with everything except the new card details. Every extra field, navigation menu, or unrelated promotion is a tax on a person who arrived with a single intention. Log where people abandon this page the way you log API errors. A surprising share of 'unrecoverable' revenue is just a form that failed on mobile.

Layer 6: The feedback loop

Finally, recovery needs instrumentation that billing alone does not give you. Track recovery rate by decline category, not just in aggregate. Watch time-to-recovery, because money recovered in two days behaves differently from money recovered in twenty. Compare cohorts: new customers fail differently from loyal ones, and annual plans deserve different handling from monthly ones. When you change retry timing, measure it like a product experiment, with a holdout where you can manage one. Without this layer, every dunning change is an opinion.

Putting it together

None of this argues for ripping out Stripe. The opposite: the cleaner your billing foundation, the more a dedicated recovery layer can do. Audit in order. Is the ledger trustworthy? Are decline codes preserved? Do retry rules branch on the reason, or merely count attempts? Does each customer message match a real state? Does the update page work on a phone, one-handed, in under a minute?

For a broader map of how these pieces fit together, see Swipe Again's failed payment recovery overview, which frames recovery as its own discipline rather than a settings page.

Billing keeps the books. Dunning does the recovering. When a team respects that boundary — in code, in data, and in ownership — failed payments stop being mysterious churn and become what they mostly are: a queue of specific, fixable problems, each with a reason attached.

Top comments (0)