Retry queue

A holding area for temporarily failed messages, spacing out later attempts so an outage does not lose mail or trigger a retry storm.

the list of emails waiting to try againkeep failed emails and resend laterour email provider went down and we dropped messagesrety queuedelayed send queuemessages stuck waiting for another attemptwhy did the same email go out twicedon't lose email when the provider is down

See it

Live demo coming soon

What it is

A retry queue holds a message after a temporary failure and schedules another attempt later. Each job needs an attempt count, a 'next_attempt_at' time, the last error, and a delivery deadline. A good worker spaces attempts with exponential backoff plus jitter, so an outage does not end with every delayed message hitting the same server in the same second.

Use one for failures your application still owns: a timeout before an API request completed, an HTTP 429, or a retryable 5xx from the sending API. Once Amazon SES, Postmark, or another ESP has accepted a message, the ESP owns its SMTP queue and its retries after receiving-server 4xx deferrals. Enqueuing a second copy in your application at that point creates duplicates instead of resilience.

Uncertainty is the hard part. A request can time out after the provider accepted it but before your app received the message ID. Blindly retrying that ambiguous result can send twice. Give every logical message a stable idempotency key where the API supports one, make the queue consumer safe under duplicate delivery, cap attempts, and move exhausted jobs to a dead-letter queue for inspection.

Ask AI for it

Build an email retry queue on Amazon SQS with a dead-letter queue. Store a stable logical message ID, attempt count, next attempt time, last error, and delivery deadline. Retry only transport timeouts, HTTP 429 responses, and retryable 5xx responses from the send API, using exponential backoff with full jitter and a hard attempt cap. Make the consumer idempotent because SQS provides at-least-once delivery. Once the provider returns an accepted response and message ID, mark the job submitted and never create another application-level send because of later SMTP deferrals; the provider owns those retries. Put ambiguous timeouts on a reconciliation path instead of blindly resending, and send exhausted jobs to the dead-letter queue with enough context to replay one safely.

You might have meant

soft bouncesmtp deferral and greylistingthrottling rate limitingemail delivery event webhooksbounce processing