How would you design an idempotent order confirmation email sender?

Tests preventing duplicate side effects in distributed systems. Strong answers use deduplication keys, idempotency windows, and distinguish client retries from broker redelivery. Red flag: using a read-before-write check without unique constraints or TTLs.
WHAT THIS TESTS: This question probes whether you understand that at-least-once delivery is the default in distributed messaging and that side effects like email cannot be undone. The interviewer cares if you separate business semantics from infrastructure guarantees and if you can build a deterministic deduplication boundary around an external non-idempotent third party.
A GOOD ANSWER COVERS: A strong response walks through four mechanisms in order. First, generate a unique idempotency key at the source such as a UUID derived from the order confirmation event rather than relying solely on the order identifier. Second, store that key in a deduplication ledger before calling the email provider using a datastore with fast point lookups such as Redis or a relational table with a unique constraint. Third, set a TTL or sliding window on that ledger for example seven to thirty days because infinite storage is impractical and replay windows are always finite. Fourth, handle the partial failure scenario where the email provider accepts the send but your service crashes before committing the key typically by making the ledger write atomic with an outbox pattern or by treating the provider message ID as the key and reconciling asynchronously.
COMMON WRONG ANSWERS: The biggest red flag is a naive read-before-write check like querying a sent_emails table and skipping if a row exists because that race condition allows duplicates under concurrent processing. Another red flag is using only the order_id as the deduplication key which breaks if the order triggers confirmation shipping and refund emails or if the order is amended and reconfirmed. Suggesting exactly-once broker semantics as the fix is also wrong because brokers guarantee at-least-once delivery to the application layer.
LIKELY FOLLOW-UPS: The interviewer may ask how you would handle a duplicate event that arrives after the TTL expires how to scale the deduplication store horizontally without hot keys or what happens if the email provider itself retries an API call due to a network timeout. They might also ask how to test idempotency under load perhaps by injecting duplicate events at one thousand per second and measuring the duplicate send rate.
ONE CONCRETE EXAMPLE: Suppose an order confirmation event carries event_id abc-123. Your consumer hashes that id and performs a SET NX in Redis with a key like idempotency:email:abc-123 and an expiration of 604800 seconds. Only if the SET returns success do you invoke the email provider. If the consumer crashes after the provider returns HTTP 202 but before the Redis write the outbox table pattern ensures the key is still committed when the transaction replays preventing a second send on restart.
Read the original → enterpriseintegrationpatterns.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.