Do I need…idempotency keys?

IDEALLY

(if your code retries)

Networks fail mid-request and retries are how you cope—but a retried send without an idempotency key is how a customer gets three copies of one receipt. One header makes retries safe.

The long answer ↓

Here’s the failure mode: your code calls the email API, the request times out, and you retry—sensible. Except a timeout doesn’t mean the request failed; it means you didn’t hear the answer. If the first attempt actually went through, your retry just sent the email twice. Email is the worst place for this bug, because the duplicate lands somewhere a human is guaranteed to look.

What a key does

An idempotent operation can run more than once with the same input and produce the same outcome, side effects included—which for email means: sent exactly once. You opt in by attaching a unique key to each logical send:

Idempotency-Key: order-confirmation-8412

Retry with the same key and the API recognizes the operation, returns the original result, and does not send again. The key should identify the event, not the attempt—derive it from something stable like order-confirmation-${orderId}, never a random value generated per request (that would defeat the whole mechanism).

When it matters

On Resend it’s the Idempotency-Key header (or the equivalent SDK option) on the send-email endpoint.

The verdict logic

This is an ideally rather than a yes because a low-volume app doing fire-and-forget sends with no retry logic has nothing to protect against—no retries, no duplicates. But the moment there’s a retry path anywhere between your event and the send call (and in production systems there almost always is), the key is one line of code that removes a whole class of embarrassing bugs. Cheap insurance, like a plain-text part, but for your reputation with your own customers.