Most dunning compliance advice is written for lawyers and read by nobody. Meanwhile the actual decisions — how many texts you may send, what the email must say, when consent was recorded and where that record lives — get made by whoever writes the retry job. If compliance lives in a PDF nobody opens, it does not live anywhere. It has to survive as checks in the codebase and fields in the schema.
Start with consent, because everything else hangs off it. For email, the rules are comparatively forgiving: a transactional notice about a failed payment to an existing customer sits on solid ground in most jurisdictions, provided it is actually about the payment and carries working identification and opt-out mechanics where the law requires them. SMS is stricter everywhere. In the US, marketing texts need express written consent; transactional texts still need a defensible consent record, a recognizable sender, and a functioning STOP path — and “the customer gave us a number at checkout” is a thinner record than most teams assume. Store the consent event like you store a payment event: timestamp, surface, exact language shown, and the number it applied to. If you cannot query it, you do not have it.
Second: frequency is a compliance surface, not just a UX one. Several regimes and carrier rules treat repeated automated messages as a category problem regardless of content. Cap your sequences in code, per channel, per customer, with the caps visible in one config file a reviewer can read. A dunning flow that can send nine touches because three separate jobs each think they own three is a bug with legal consequences.
Third: content constraints are checkable. No threats you cannot carry out (“your account will be deleted tonight” when it will not be), no invented deadlines, no fees described that the contract does not support, and in the EU and UK, consumer-protection rules on top of the privacy ones. Write these as lint rules for templates: banned phrases fail the build, required elements (business identity, a real reply path, the actual amount) are asserted present. Templates change often; the checks should run every time they do.
Fourth: data handling. Card-update links should be tokenized, single-purpose, and expiring; logs should never carry full card data (they should not carry it at all — that is what your processor’s vault is for); and retention needs a number, in days, that somebody chose on purpose. “Forever” is not a retention policy, it is an accident in progress.
None of this is exotic. It is the same discipline as idempotency keys and webhook signature checks — boring, testable, and much cheaper before the first regulator or carrier asks than after. If you want the whole thing as a pass/fail list you can work through with your own stack open beside it, a compliance checklist for dunning that a developer can actually implement covers consent records, channel rules, content constraints, and data handling in implementation order.
Finally, build the audit drill before anyone asks for it. Once a quarter, pull a random sample of twenty dunning sends across channels and reconstruct each one’s paperwork from the system’s own records: the consent event behind the number or address, the frequency cap in force at send time, the template version that produced the copy, and the suppression checks that ran. Time the exercise. If a single send takes an afternoon to document, the records exist on paper but not in practice, and that gap — not any individual rule — is the real compliance risk. The drill has a side benefit engineers appreciate: it is a standing test of the logging nobody otherwise exercises until an incident, and it turns “we keep good records” from an assertion into a measured retrieval time.
Treat the checklist like a test suite: run it when the flow changes, not when someone remembers. That habit — compliance as a maintained property of the system rather than a document about the system — is the core of Swipe Again’s recovery work, and it is available to any team willing to write the checks down.
Top comments (0)