Engineering

Why Your System Sends Duplicate Emails
(And It’s Not a Bug)

6 min read

A user signs up. They get the welcome email. Then they get it again. And again. You check logs — everything “succeeded.” No crash. No exception.

The TL;DR

Duplicate emails are rarely caused by coding errors. They are usually the result of network timeouts and automatic retries. If your server sends an email but doesn't receive a confirmation from the API provider (SendGrid, SES, etc.) due to a network blip, it assumes failure and sends the request again—resulting in two identical emails.

This is one of the most common production issues in SaaS systems. And it rarely comes from bad code—it comes from the fact that exactly-once processing is a myth in network communications.

🚨 The Real Cause: Retries, Not Logic Errors

Email systems break not because your logic is wrong, but because of infrastructure uncertainty.

  • Your API call timed out
  • The email provider responded slowly
  • A webhook or automation step was retried
  • An AI agent repeated the action because of a context reset

💥 Why Email Is Especially Vulnerable

Email APIs (SendGrid, SES, Mailgun, etc.) often accept the request, queue the email, and then respond. If they respond slowly or the connection drops before you get the confirmation, your system retries. Unlike database records, which you might catch with a unique index, an email sent to an API is "gone" once the provider accepts it.

Email sending is not transactional. There is no built-in exactly-once guarantee in the cloud.

❌ Common Fixes That Don’t Work

You cannot rely on email APIs for execution safety. Most "easy" fixes fail under production load:

Attempt Why it fails
Add a delay Retries still happen later, and it hurts user experience.
Check user state Race conditions allow two calls to check "sent: false" at the exact same millisecond.
Log sent emails Doesn’t prevent the external provider from queueing the second request.

✅ The Safe Way to Send Emails

Email sending must be idempotent. This means the same email action can be requested multiple times but results in only one actual send. This is the same principle used to prevent double charges on checkout buttons.

Instead of Your system → Email API, you do:

Your system → Idempotency Layer → Email API

The layer uses a key (e.g., user_id + event_type), stores the result of the first execution, and blocks duplicate sends. Retries stop being dangerous.

❓ Frequently Asked Questions

Why don't SendGrid or AWS SES handle this for me?

Most email providers are designed for high throughput, not strict transactional safety. While some offer "Idempotency-Key" headers, they are often limited to short windows or specific API versions. A centralized idempotency layer ensures safety across all your providers.

What should I use as an Idempotency Key for emails?

For a welcome email, `welcome_email_{user_id}` is perfect. For a password reset, `pw_reset_{token_id}`. The key should represent the *intent* of the email.

Can retries happen even if I use a queue like SQS?

Yes. SQS and similar queues guarantee "at-least-once" delivery. If your worker processes the message and sends the email but fails to delete the message from the queue (due to a timeout), SQS will deliver the message again to another worker.

How does OnceOnly prevent these duplicates?

OnceOnly acts as a gatekeeper. Your server calls /v1/check-lock with a stable key (e.g. welcome_email_{user_id}) before sending. If OnceOnly returns status=duplicate, you skip the send and return a safe “already sent” response (or your cached result) without touching your email provider again.

🧩 Why This Keeps Happening in SaaS

Email feels “simple,” so teams don’t treat it as a distributed system problem. But as soon as your app uses webhooks, automation tools, or AI — duplicate requests become the norm, not the exception.

🚀 The 5-Minute Fix

Add an idempotency layer designed for automation and API-driven systems. It guarantees safe retries, no duplicate emails, and predictable behavior under failure.

Secure Your Email Flows

Stop spamming your users with duplicate notifications.