The requirement: a message must always exist
Recovery messaging has an unusual reliability property. A failed generation is not a degraded experience, it is a lost subscription — the customer never learns their payment failed, the grace period expires, and the churn is recorded as if they had chosen to leave.
That rules out the common pattern of calling a model, catching the error and logging it. Any architecture where an upstream outage produces zero messages is unsuitable, no matter how good the copy is on a healthy day.
The design goal, then, is not the best possible message. It is a guaranteed acceptable message within a bounded time, with quality degrading gracefully rather than availability failing sharply.
Tier 0 — the historical cache
Before any model call, look up previous messages for the same workspace and the same decline reason within a recent window, preferring ones whose payment subsequently recovered.
A cache hit returns in milliseconds, costs nothing, and is empirically the best-performing copy you have for that situation, because it already worked. Substituting only the volatile fields — amount, card last four, retry date, product name — keeps it accurate.
Scope the cache per workspace, never globally. Tone, product naming and brand voice differ between tenants, and a cross-tenant cache leaks one client's phrasing into another's customer conversation.
Tier 1 — the primary model
On a cache miss, call a fast, inexpensive general model with a tightly structured prompt: the decline reason, the amount and currency, the retry schedule, the brand voice, the channel constraints and a required JSON output shape covering email subject, email body, WhatsApp text and a recovery score.
Cap the call at 3.5 seconds. Recovery copy is not worth a long tail — a slow perfect message is worse than a fast good one because the whole pipeline is queued behind it.
Validate the response against a schema before accepting it. A model that returns prose instead of JSON, omits the WhatsApp field, or exceeds the template character limit has failed, and failure should fall through to the next tier rather than emit a broken message.
Tier 2 — the fallback model
The second tier exists to survive provider-level incidents, not to produce better copy. It should be a different model, ideally on a different provider, with the same prompt contract and the same 3.5-second cap.
Because it runs only when tier one has already failed or timed out, worst-case latency before templates is roughly seven seconds. That is acceptable for an asynchronous pipeline and far below the point where any customer notices.
Keep the prompt identical across both tiers. Divergent prompts create a quality cliff that is invisible until an incident, which is exactly the wrong time to discover it.
Tier 3 — deterministic templates
The final tier is plain string interpolation over hand-written templates, one per decline code, with no network call and no failure mode. It cannot be slow, cannot be rate-limited and cannot be down.
These templates should be genuinely good, not placeholders. Write them the way you would write the AI prompt's ideal output: name the cause, state the amount, state the retry date, offer the update link, keep it under three short lines for WhatsApp.
In practice a well-written deterministic template performs close to AI-generated copy for the four common decline codes, because the information content is fixed and the persuasion budget is small. The AI tiers earn their place on personalisation and tone, not on the core facts.
Latency budget and queue design
Return 200 to the payment provider's webhook immediately and generate asynchronously. A handler that waits on the cascade will eventually exceed the provider's timeout and trigger delivery retries that your idempotency layer then has to absorb.
Budget the whole cascade at under eight seconds worst case: cache lookup in milliseconds, two capped model calls, then instant templates. Alert on the ratio of tier-three fallbacks rather than on individual failures — a rising fallback rate is a provider incident or a prompt regression.
Re-check payment state immediately before dispatch. Generation is asynchronous, and a payment can recover between queueing and sending.
How much of your involuntary churn is recoverable?
Compares a 40% single-channel baseline against the 63.8% RRLabs platform average.
- At risk / month
- $5,600
- Extra recovered / month
- $1,333
- Annualised, less $3,000 plan
- $12,994
RRLabs vs legacy dunning tools
Churn Buster, Baremetrics Recover, Stripe native dunning and Gravy compared with Revenue Recovery Labs.
| Feature | Legacy tools | Revenue Recovery Labs |
|---|---|---|
| Recovery channels | Email and basic SMS only | Native Meta WhatsApp Cloud API (your number) + email |
| Pricing architecture | $129–$629+/mo, or a percentage cut of recovered cash | Flat $100 / $250 / $500 per month — you keep 100% |
| Retry logic | Fixed calendar dunning (day 1, 3, 7) | Retry window derived per decline code, persisted at ingestion |
| Copy engine | Static templates you edit by hand | 4-tier cascade: cache → primary model → fallback model → deterministic templates |
| White-label | Unavailable or enterprise-only | Flat +$300/mo with custom domain and no vendor watermark |
| Audit trail | Send logs at best | Tier, model, latency and recovery score on every message |
Auditability: the part teams skip
Log every generation with the tier used, the model identifier, the latency in milliseconds, the decline reason, the recovery score and the final message body. Without this you cannot answer the two questions that always come: why did this customer receive this text, and is the AI actually better than the template?
The audit trail is also the training signal for tier zero. A message whose payment recovered is a cache candidate; one whose payment did not is not.
For white-label deployments the log is a compliance requirement rather than a nicety, because the agency's client will eventually ask exactly what was sent under their brand.
Evaluating whether the AI tiers earn their cost
Run a periodic holdout: route a small random share of failures straight to tier three and compare recovery rates against the cascade over a full billing cycle.
If the gap is small on the four common codes but large on unusual ones, the correct conclusion is not to remove the AI tiers but to narrow them — templates for the predictable majority, models for the long tail.
Measure cost the same way you measure everything else here: in cents per recovered dollar. A cascade that adds a fraction of a cent per message and lifts recovery by even a point is not a close call.
Prompt contract and output validation
Both model tiers share one prompt contract: a system instruction describing the brand voice and channel constraints, a structured user payload with the decline reason, amount, currency, card last four, retry timestamp and product name, and a required JSON schema for the response.
Validate the parsed output before accepting it: required fields present, WhatsApp text within the template character limit, email subject under a sensible length, no placeholder tokens left unresolved, and a recovery score inside the expected range.
Treat validation failure exactly like a timeout — fall through to the next tier. Emitting a malformed message is strictly worse than emitting a deterministic one.
Multi-tenancy and prompt isolation
In a multi-tenant deployment, every prompt must be scoped to one workspace: its brand voice, its product name, its currency conventions and its own cached history. Cross-tenant contamination in generated copy is a trust failure that no amount of quality improvement compensates for.
Enforce it at the data layer, not in the prompt. Row-level security on the workspace identifier means a bug in the generation code cannot read another tenant's messages even if the prompt is wrong.
The same boundary applies to the audit log. Each tenant's clients may eventually ask to see exactly what was sent under their brand, and the answer must be scoped and complete.
Where RRLabs fits
Revenue Recovery Labs implements this cascade in production: a 30-day per-workspace cache keyed on decline reason, a primary model, a fallback model on a different provider, both capped at 3.5 seconds, then hardcoded per-code templates that cannot fail.
Each run returns an email subject, an email body, WhatsApp text, a recovery score and a suggested retry delay, and writes an audit row with the tier used and the end-to-end latency in milliseconds.
Tenants are isolated by row-level security on the workspace, and pricing stays flat at $100, $250 or $500 per month regardless of how many messages the cascade generates.