IOSOR Learn

DLR failed retry policy under prepaid: when to retry and when to stop spending

Failed, rejected, and expired are not one word. Every prepaid retry is a debit. Share a status dictionary before you write the cap, or the wallet burns in a dead corridor.

"It failed" is not a status, and the retry button is not a strategy. Under prepaid, every automatic retry is a ledger line — not a free courtesy. undelivered, rejected, and expired demand different acts. Product that hammers retry until the wallet is empty is chasing conversion while finance pays the second and third attempt to a dead number. Agree the dictionary before the loop, or the incident becomes a vocabulary fight at 02:00.

IOSOR runs white-label prepaid messaging with one DLR vocabulary in the dashboard, the webhook, and the export. A corridor marked live may admit a capped retry; in setup does not open "on the next try." See undelivered, rejected, expired and DLR, latency, and failover. Near USD 1,000+ monthly usage, retry debits bucketed by status enter a tighter commercial read. Evidence first, then scale.

Status dictionary before retry logic

Print terminal statuses into a table product, ops, and finance can point at. Retry without a dictionary burns money. When delivered rates dip, follow the SMS low-deliverability playbook before anyone writes "until delivered."

Status Automatic retry? Who signs
Delivered No Nobody
Undelivered / failed With a cap Ops
Rejected No (change the payload) Product
Expired No (fix TTL) Product

If support cannot map a ticket to one of those rows, you do not have a retry policy. Freeze ownerless auto-retries until the table is signed.

Failed vs rejected vs expired

Failed / undelivered means the platform handed the job over and the terminal did not confirm. If the corridor is healthy, a capped retry can save a conversion. Rejected is a network or policy refusal: the same number and the same body almost always refuse again and debit again. Expired is time: TTL shorter than corridor latency, or a queue before send. Treating expired as failed and hammering retries only multiplies expired rows. An OTP that arrives outside the window no longer converts — the wallet still pays. Do not conflate user-initiated resend with system failover; they look the same in a ticket and they must not look the same in the ledger.

Retry caps and wallet impact

Cap automatic attempts per message. Each attempt must match a correlation ID in the ledger. "Until delivered" without a cap empties prepaid on a dead corridor.

Product vs finance ownership

Product owns the policy: which statuses allow retry, TTL, resend cooldown. Finance owns visibility: whether each attempt debits, whether the export matches the webhook.

Red flags

  • Only sent and failed exist, but automatic retry is on
  • Three identical hits on a rejected payload
  • Expired treated as a network outage
  • System failover and user resend on the same debit line
  • "Until delivered" with no attempt cap
  • Retry promised while the catalog is in setup
  • Finance export missing attempt number

Start with IOSOR

Fill the dictionary: failed versus rejected versus expired. Cap auto-retry so each failed DLR does not open a new prepaid debit. The user’s resend button is separate from the system attempt. Prove the cap on two live corridors at low volume.

IOSOR takeaway

Failed DLR retry is a spend cap, not an infinite loop.

Do: classify the terminal status, cap retries, export user-resend apart from the system attempt. Don’t: auto-retry rejected or expired as if they were transient failed.

Was this guide helpful?

Related guides