- What should a worker do when a provider call fails?
- How many times should we retry, and how should we schedule those retries?
- When should we stop retrying and move work to a dead-letter queue (DLQ)?
- Avoid amplifying the outage by sending many immediate retries (prevent a thundering herd).
- Ensure transient failures are retried automatically and successfully.
- Preserve failed messages for investigation and reprocessing if necessary.
- Keep behavior predictable: cap retry attempts and delays, monitor DLQ growth, and provide tooling for replay.
- Wait 1 second before the first retry.
- If that fails, wait 2 seconds before the second retry.
- If that fails, wait 4 seconds before the third retry.
- If attempts are 1-indexed: backoff = base_delay * 2^(attempt_number - 1)
- If attempts are 0-indexed (attempt 0 = first retry): backoff = base_delay * 2^(attempt_number)
- base_delay = 1s → attempt 1 = 1s, attempt 2 = 2s, attempt 3 = 4s
- Apply an upper cap:
max_delay = 60s(so backoff never exceeds this) - Add jitter:
delay = random_between(backoff * 0.5, backoff * 1.5)
Include jitter (a randomized offset) with exponential backoff to prevent a thundering herd when many workers retry simultaneously. Also cap the maximum delay and limit the number of retries to keep behavior predictable and measurable.

- Preserve failed messages for debugging and auditing.
- Prevent poison messages (bad or malformed payloads) from blocking normal processing.
- Allow manual inspection and corrective actions (e.g., fix data and replay).
- Trigger alerts and metrics when DLQ size grows beyond a threshold.
Operational considerations
- Distinguish between provider outages and poison messages: persistent 5xx/provider-timeout errors are candidates for DLQing, while malformed payloads should be DLQed immediately.
- Define SLAs for how fast problems must be fixed and what constitutes an outage that requires paging.
- Implement visibility: annotate DLQ messages with failure reason, attempt count, timestamps, and correlation IDs to make debugging easier.
- Use idempotent operations or deduplication when reprocessing messages from DLQ to prevent side effects.
Do not silently drop failed notifications. Moving messages to a DLQ preserves them for post-mortem analysis and prevents repeated failed processing from affecting healthy traffic.

- Exponential backoff and jitter patterns — industry best practices for retries.
- Dead-letter queue patterns — for preserving failed messages, monitoring, and replay.
- AWS SQS Dead-Letter Queues (example platform docs).
- For general system-design concepts: queueing, idempotency, monitoring, and alerting strategies.