Retries are part of operating a networked application. A connection can close before the client receives a response, even when the server has already processed the request. Email makes this especially visible: a careless retry can put two receipts in the same inbox.
Model the business event first
Choose a stable identity for the intended message, such as a booking-confirmed event ID. Store that identity when you decide to send. Generating a random key inside every retry attempt defeats the purpose because each attempt then looks unrelated.
Sendar accepts an Idempotency-Key on single-email POST requests. The documented format is 16–128 letters, digits, underscores, colons or hyphens. Keep both the key and the message payload unchanged when retrying the same event.
Treat a conflict as a reason to inspect
A conflict can indicate a different payload associated with the same key or a pending or uncertain operation. Do not “fix” it by swapping in another key. Check the response details and email history to establish whether the original message exists.
The same principle applies to timeouts. The absence of a response on your side does not establish the absence of a send on the provider side. Store attempts in a durable application record so a restarted worker can continue the investigation rather than treating everything as new.
Separate errors that need correction
Invalid recipients, missing credentials and a sending-domain problem do not become valid through repetition. Correct those conditions before resubmitting. Quota and transient availability failures need different operational handling, with bounded retries and a path for human inspection when the outcome remains unclear.
Our batch endpoint has no documented idempotency guarantee. Do not copy a single-message retry loop around an uncertain batch request. You may need to track individual intended messages and reconcile their outcomes before proceeding.
Keep a deliberate resend distinct
Sometimes the user intentionally requests another confirmation. That is a new business action, subject to your application's limits and authorisation. Record it separately from a transport retry. This distinction lets you explain why two messages exist without weakening protection against accidental duplicates in the normal path.