DEV Community

Swipe Again for Swipe Again

Posted on

When a Chargebee Retry Meets a Card That Was Already Replaced

Every billing team has lived some version of this scene. A subscription payment fails on a Tuesday. The retry schedule does its quiet work, the customer gets an email, clicks through, and updates their card. Problem solved — except that on Thursday the platform retries the old card anyway, because the update landed in one place and the retry was still queued against the payment method that existed when the invoice first failed. Now there are two stories about the same invoice, and only one of them is true.

This is not a Chargebee bug so much as a sequencing problem, and sequencing problems are where dunning quietly succeeds or fails. An invoice is not a single event. It is a small timeline: the first attempt, the decline that comes back, the retries that follow, the messages that go out alongside them, and the moment the customer acts. If any one of those steps is working from a stale snapshot of the customer's payment method, the timeline forks.

The first fork is the payment-method snapshot. When a customer updates a card from a dunning email, the new card needs to become the card of record for the pending invoice, not just for the next renewal. Teams assume the update propagates everywhere. Often it does. But "often" is doing a lot of work in that sentence, especially when the update arrives through a hosted page, a vault token, or a customer portal session that was opened before the retry was scheduled. The practical test is simple: after a mid-dunning card update, look at the next retry attempt and ask which payment method it actually used. If you cannot answer that from your logs, you have found a gap worth closing before it costs you a customer who did everything right.

The second fork is the message timeline. A customer who has already updated their card should never receive a "your payment failed, please update your card" email afterwards. It sounds obvious, and yet it is one of the most common complaints support teams hear about dunning, because the email queue and the payment state are usually owned by different systems. The email was true when it was queued. It is false when it arrives. Customers do not grade on intent; they grade on the inbox. Every message in a dunning sequence should check the current state of the invoice at send time, not at schedule time, and suppress itself if the debt it describes no longer exists.

The third fork is quieter: the duplicate-payment fear. When a customer pays an overdue invoice manually — through a link, a portal, or a support-assisted payment — any retry still pending against that invoice has to die immediately and visibly. A double charge on a recovered invoice does more damage than the original failure. It converts a save into a chargeback risk and a support escalation. Mature dunning setups treat "invoice paid by any route" as a terminal signal that cancels every other route, and they log that cancellation so a human can prove it happened.

None of this requires exotic tooling. It requires treating dunning as a state machine instead of a calendar. A calendar says: retry on day one, day three, day seven; email on day zero, day four, day ten. A state machine says: retry only if the invoice is still unpaid, the payment method on file is still the one that failed or a deliberate successor to it, and no customer action in the last few hours has changed the picture. The calendar is easier to build. The state machine is the one that respects the customer.

If you want the fuller picture of how dunning works inside Chargebee — the retry timing, the email cadence, and where a recovery layer sits alongside the billing platform rather than inside it — we keep our notes public and update them as the platform changes.

We build recovery tooling for subscription businesses that would rather fix the timeline than send more email about it. — Swipe Again

Top comments (0)