martechdevs has been acquired by Growth and Analytics Partners LLC

SaaS Dunning Workflows: Recover Payments Without Confusing Customers

Jafrin Akter Alo

Data Engineer and Co-founder, martechdevs

Last updated 9 min read

Blog cover: SaaS Dunning Workflows: Recover Payments Without Confusing Customers

A useful SaaS dunning workflow coordinates payment retries, customer instructions, account ownership and product access around the current invoice state. It stops reminders when the debt is resolved and changes the request when customer action is required. Build one recovery case per invoice, then make every scheduled message recheck that case before sending.

Last updated: 18 September 2026.

A failed renewal is not automatically a lost customer. It is also not permission to send the same urgent email after every webhook. The customer may need to replace a card, authenticate a payment, involve accounts payable or do nothing while an appropriate retry runs.

The operating problem sits between billing, product and lifecycle messaging. If these systems disagree, our martech integration work starts by deciding which system owns the invoice state and how the others receive reliable updates. This guide uses Stripe's documented behaviour for concrete examples, while the recovery design applies more broadly.

What should a recovery case represent?

Use the invoice as the primary case boundary. Keep the account, subscription and billing contact as related entities. One account may have several subscriptions, and one subscription may have more than one outstanding invoice. A single payment_failed = true field on the contact loses that distinction.

An illustrative recovery record could contain:

Plain text
case_id: internal recovery case identifier
provider_invoice_id: billing platform invoice identifier
account_id and subscription_id: related business entities
opened_at: first relevant payment failure
amount_remaining and currency: current billing values
collection_method: automatic charge or invoice collection
action_required: retry, authenticate, replace method, manual review
next_attempt_at: latest verified retry time, if known
case_status: open, resolved, waived, voided, escalated
billing_contact_id: verified recipient
last_message_step and sent_at: communication history
source_checked_at: last current-state reconciliation

These are proposed application fields, not a Stripe API schema. Store only the operational information needed for recovery. Payment credentials belong in the payment provider's approved collection flow, not in your CRM, email platform or webhook logs.

The recovery case should explain what needs to happen next. A new failed attempt updates the existing case. It should not automatically open a new sequence that competes with the previous one.

Which failures need different customer instructions?

Separate a recoverable retry from a failure requiring intervention. Stripe documents situations where automatic retries do not execute, including hard declines and missing payment methods. Its subscription webhooks also distinguish invoices requiring customer authentication. Payment retries, subscription events.

For a retryable problem, tell the customer what happened and whether an action is currently necessary. For a required authentication, direct them to complete that authentication. For an unusable payment method, provide a secure way to replace it. For an invoice requiring a purchase order or bank transfer, route the case to the person who can resolve that process.

Avoid interpreting every provider error as an explanation you can safely put in customer-facing copy. The message should reflect the supported action, not speculate about the customer's funds or financial circumstances. An internal failure classification can remain more detailed than the email.

Define a manual-review route for ambiguous states. A disputed amount, duplicate invoice allegation or contract disagreement requires an owner with authority to investigate. More automated reminders will not resolve the underlying issue.

Who owns retries, and who owns the message?

Let one system own the retry policy. If the billing provider already schedules collection, the lifecycle workflow should observe it rather than independently create additional attempts. Stripe's Smart Retries and custom schedules have their own configuration, restrictions and end states. Retry configuration.

Keep the communication owner equally clear. Stripe can send failed-payment emails and payment-confirmation instructions. If your lifecycle platform also sends them, inventory both systems before launch and choose which sends each customer-facing step. Customer email settings.

A practical division might be:

  • Billing owns payment attempts, invoice balances and settlement.
  • The lifecycle system owns the approved communication sequence.
  • Product owns the implemented access policy.
  • Finance owns invoice exceptions, credits and manual collection decisions.
  • Customer success owns personal escalation for the accounts assigned to it.

This division still requires a shared state model. A customer-success owner should see whether payment succeeded before calling. The product should see the approved grace policy rather than infer it from an email being sent.

For a CRM using HubSpot, the Stripe and HubSpot integration guide can help with that mapping. Keep the authoritative payment decision in billing while exposing enough context for the account team to act.

How do you prevent duplicate or stale reminders?

Stripe does not guarantee webhook order, and deliveries can repeat. Its documentation recommends tracking processed event IDs and using current API objects where needed. A webhook timestamp alone cannot establish a reliable total ordering. Webhook delivery behaviour.

Use a durable event-receipt log, then update the recovery case from the relevant current invoice and subscription state. Separately record each communication step so retrying a worker does not automatically resend the same email. These are two different forms of duplicate protection: event processing and customer communication.

Immediately before a scheduled send, evaluate the current case again. If the invoice is paid, voided or otherwise resolved under the finance policy, cancel the reminder. If a manual-review hold is active, route it to the owner. If a different action is now required, update the message rather than send outdated instructions.

Be careful with retry timing. Stripe documents that accounts using Automations receive next_payment_attempt updates through invoice.updated rather than the failed-payment webhook. Updating the wrong default-payment-method field can also leave the subscription retrying its previous method. Retry events and payment-method precedence.

These details matter because “we will retry tomorrow” is a promise. Only include a specific date when it comes from the current authoritative schedule and your system can keep the message accurate. Otherwise, explain the next action without inventing timing.

What does a complete workflow look like?

Consider an illustrative monthly SaaS subscription with an unpaid $240 renewal. The company has chosen a seven-day grace period for this plan. That duration is a business policy for this example, not a recommended default or a statement about Stripe's settings.

At the first failure, create or update the invoice's recovery case. Retrieve the current balance and required action. Notify the designated billing administrator once using the approved initial message. Keep product access aligned with the documented grace policy.

If the provider schedules another attempt, store the latest schedule. A failed retry updates the case. The messaging policy decides whether enough time has passed and whether the customer has new information to act on. It does not send simply because the attempt counter increased.

On day three, suppose the administrator replaces the payment method. The system should verify that the change applies to the subscription's actual collection path. It should not close the case merely because a card-update event arrived. The debt is unresolved until billing confirms the relevant outcome.

If the invoice is paid on day four, close the recovery case and cancel pending reminders. Reconcile subscription state and access separately. Stripe advises checking the associated subscription's current status when handling invoice.paid; a paid invoice alone does not always establish that every required balance is settled. Subscription state and access.

If the case remains unresolved near the grace deadline, escalate according to the plan's policy. State the actual consequence and the time it takes effect. Do not promise that data will be deleted or access removed unless the product genuinely implements that policy and the communication is appropriate for the contract.

How the workflow fits together
Reconcile an invoice case, stop resolved reminders, classify the required action and recheck eligibility before communication.
Open full diagram

What should the customer-facing message contain?

Give the recipient enough context to recognise the account and invoice, then one clear action. Include the product or account name, relevant amount and currency, the supported issue description, a secure action link and a route to ask for help. Describe access consequences only when they are known.

For the illustrative case, the body could read:

“We couldn't collect the $240 renewal for your Example Workspace subscription. Please open Billing in your account to review the invoice and update the payment method if needed. Your workspace remains available until 21 October under its current grace period. If someone else manages billing, reply and we'll help route the request.”

Replace the wording, dates and behaviour with your actual policy. Do not send this copy if a payment is merely pending or authentication is the required action. Those customers need different instructions.

Stripe offers hosted billing and portal experiences for payment-method and invoice management. Portal capabilities and session behaviour have limitations, so use the documented integration rather than storing an ephemeral portal-session URL as a permanent CRM property. Customer portal documentation.

An application link can authenticate the user, confirm their billing role and create the appropriate provider session. Test that an ordinary member cannot manage another account's billing by changing a URL parameter. A helpful email should not create an account-access vulnerability.

How should you measure recovery?

Measure at the case and invoice level, with a stated observation window. Track the amount outstanding when eligible cases opened, the amount collected from those invoices, cases still open, cases waived or voided and time to resolution. Keep refunds and later reversals visible where they affect the reported result.

For an illustrative cohort, 80 invoices enter recovery with $24,000 outstanding. By the agreed thirty-day observation point, $15,600 has been collected, $1,200 has been waived and $7,200 remains unresolved. The amount collected is 65% of the original outstanding balance. Waived amounts are not recovered cash.

That 65% does not establish the incremental impact of your email sequence. Some payments could have recovered through provider retries or customer action without the messages. To estimate incremental value, use a suitable controlled design that preserves essential billing notices and respects the customer contract. Do not relabel all recovered revenue as campaign-generated revenue.

Break operational results down by required action and collection method. A low recovery rate for authentication-required cases suggests a different problem from a long delay in purchase-order approval. Connect this work to churn prediction and prevention only after you can distinguish payment failure from a customer's deliberate decision to leave.

What should be tested before turning it on?

  • Deliver the same failure event twice and confirm one case and one eligible initial message.
  • Deliver a failure after a later success and confirm the paid invoice does not reopen incorrectly.
  • Resolve an invoice while a reminder is waiting and confirm the reminder stops.
  • Replace a payment method and confirm the provider uses the intended collection path.
  • Test authentication-required and manual-review cases with their own instructions.
  • Confirm the actual grace deadline, access change and restoration behaviour.
  • Check an account with two invoices so settling one does not hide the other.
  • Verify that billing-provider and lifecycle emails do not duplicate each other.

Run these as integration tests in the appropriate test environment and retain the evidence. Stripe documents specific restrictions on which customer emails it sends in a sandbox, so a missing test email needs investigation before it is treated as a workflow defect. Testing customer emails.

Start with one collection method and a clear plan policy. Add exceptions only when the team can explain the state transition, customer action and owner. That gives recovery operations a controlled path to expand.

Questions people ask

How many dunning emails should we send?

Choose the sequence from the required actions, retry schedule and grace policy. Every message should add useful information or a meaningful reminder at an appropriate time. Track complaints and duplicate contacts alongside recovery rather than assuming more messages produce a better outcome.

Should every failed payment cancel the subscription?

Use the subscription's configured recovery and access policy. A first failed renewal, a failed initial purchase and an unresolved invoice after the grace period are different states. Align finance, product and messaging before automating their consequences.

Is updating the payment method the same as recovering revenue?

No. It is an intermediate action that may enable collection. Close the invoice's recovery case using the authoritative resolved state and report collected money separately from customer actions.

Can marketing own dunning by itself?

Marketing can own message quality and orchestration, but billing owns balances and collection while product owns access. Finance and customer success need clear exception routes. Give the whole workflow one accountable operational owner with those teams supporting it.

Should we offer a discount when payment fails?

First establish whether price is the issue. A payment-method problem may need a secure update, and an accounts-payable delay may need an invoice or purchase order. Discounts should follow an approved retention policy rather than be an automatic response to every collection failure.

Sources

  1. Stripe payment retries. Accessed 18 September 2026.
  2. Stripe customer recovery emails. Accessed 18 September 2026.
  3. Stripe webhook delivery and handling. Accessed 18 September 2026.
  4. Stripe subscription webhooks and statuses. Accessed 18 September 2026.
  5. Stripe customer portal. Accessed 18 September 2026.

Written by

Jafrin Akter Alo

Data Engineer and Co-founder, martechdevs

Jafrin Akter Alo is a data engineer and co-founder of martechdevs, where the team has delivered 74+ martech, data and growth stack implementations.

Book a Free Audit

A free audit of your stack and what it needs. No pitch.

Thirty minutes, and you leave with a plan

We look at what you have, what it is costing you and what to do about it first.

  • 30 minutes
  • Video call, link on booking
  • No obligation

What we'll cover

  • Your current stack and where it hurts
  • Quick wins we can ship first
  • An integration roadmap
  • Timeline, scope and next steps

Calendar not loading? Open it in a new tab or email hello@martechdevs.com.