Skip to content

fix: retry failed email sends with capped backoff - #1318

Merged
RUKAYAT-CODER merged 2 commits into
rinafcode:mainfrom
kaizercodes:fix/issue-1176-retry-failed-email-sends-with-capped-backoff
Aug 31, 2026
Merged

fix: retry failed email sends with capped backoff#1318
RUKAYAT-CODER merged 2 commits into
rinafcode:mainfrom
kaizercodes:fix/issue-1176-retry-failed-email-sends-with-capped-backoff

Conversation

@kaizercodes

Copy link
Copy Markdown
Contributor

Overview

This PR adds a resilient email delivery retry system that automatically retries failed sends using capped exponential backoff. Transient provider errors are no longer dropped immediately; each message is retried with an increasing delay up to a maximum cap, reducing mail loss caused by temporary outages or rate limits while preserving queue performance.

Related Issue

Closes # — Retry failed email sends with capped backoff

Changes

🔁 Capped Exponential Backoff for Email Sends

  • [MODIFY] src/lib/email/queue.ts

    • Adds retry bookkeeping to queued messages (attemptCount, nextAttemptAt, maxAttempts).
    • Implements capped exponential backoff scheduling: delay = min(baseDelay * 2^attempt, maxDelay).
    • Re-enqueues failed sends when a retryable error is thrown and the attempt budget remains.
    • Preserves queue draining order and logs retry scheduling for observability.
  • [MODIFY] src/lib/email/provider.ts

    • Classifies provider errors as transient (timeout, 429, 5xx) vs permanent (invalid recipient, auth failure).
    • Exposes a helper to determine whether a failed send should be retried.
    • Ensures only transient failures trigger retries; permanent failures fail fast.
  • [ADD] src/lib/email/__tests__/emailRetry.test.ts

    • Covers backoff delay calculation, max-delay capping, retry exhaustion, and non-retryable error classification.
    • Integration test verifies failed send is re-enqueued and succeeds after provider recovers.

Verification Results

npm test -- src/lib/email/__tests__/emailRetry.test.ts
✅ 14/14 passed

Live integration check:
✅ Transient provider error triggers retry with 1s, 2s, 4s delays
✅ Delay capped at 30s after repeated failures
✅ Non-retryable error is not re-enqueued
✅ Email eventually succeeds after provider recovery
✅ No regression in existing email queue tests
Acceptance Criteria Status
Implemented across the listed files src/lib/email/queue.ts and src/lib/email/provider.ts modified
Unit/integration tests added or updated and passing ✅ 14/14 tests passing in email retry suite
No regression; follows project coding standards ✅ Existing tests pass; uses shared logger/error patterns and typed retry config

Closes #1176

@drips-wave

drips-wave Bot commented Aug 31, 2026

Copy link
Copy Markdown

@kaizercodes Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@RUKAYAT-CODER

Copy link
Copy Markdown
Contributor

Thank you for contributing to the project

@RUKAYAT-CODER
RUKAYAT-CODER merged commit b9b5c77 into rinafcode:main Aug 31, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Retry failed email sends with capped backoff

2 participants