Side by side
| Dimension | At-least-once | Exactly-once |
|---|---|---|
| Core guarantee | Delivery is retried; duplicates are possible | One committed effect per logical operation within scope |
| Repeated execution | Expected during recovery | Still possible; repeated effects must be prevented |
| Consumer responsibility | Tolerate or deduplicate repeats | Coordinate progress with committed output |
| Typical mechanisms | Durable messages, acknowledgments, retries | Atomic transactions, stable IDs, durable deduplication |
| Crash recovery | Unacknowledged work can run again | Recover without committing the same effect twice |
| External side effects | Retries can repeat an external action | Require destination cooperation or reconciliation |
| Cost | Simpler transport; duplicate handling moves downstream | More coordination and retained state; overhead depends on scope |
| Ordering | Not implied | Not implied |
The differences that matter
Separate delivery, execution, and effects. A queue can deliver a message twice, a worker can execute twice, and a database can still record only one business change. In an interview, name the exact boundary before claiming exactly-once behavior.
The critical failure window is between committing an effect and acknowledging its input. A worker that commits a database update and crashes before acknowledgment will receive the message again. Acknowledging first instead risks losing the work if the worker crashes before committing.
Exactly-once database effects can be built over at-least-once delivery. Insert a stable operation ID into a table with a unique constraint and apply the business update in the same transaction. After commit, acknowledge the message; concurrent or replayed attempts must detect the existing ID and skip the update.
Transactional stream processing can coordinate consumed offsets with output records or managed state. That guarantee does not automatically extend to an HTTP payment request, email, or arbitrary database write. Each destination needs a compatible transaction boundary or an idempotency mechanism.
Deduplication has a lifetime and an identity model. Expiring IDs before the possible replay window can allow old operations to take effect again. A stable business-operation ID also catches retries published as new messages, which broker-generated message IDs alone may miss.
Choose At-least-once when
- Repeated work is harmless, such as regenerating a thumbnail at a deterministic object key.
- You need durable asynchronous delivery and can make each consumer's writes idempotent.
- Independent services or external APIs cannot participate in one transaction, so you use retries, stable operation IDs, and reconciliation.
- Occasional duplicate effects are explicitly acceptable for the product, and stronger coordination is not worth its cost.
Choose Exactly-once when
- Duplicate committed effects would corrupt a ledger, allocate inventory twice, or inflate billable usage.
- A stream-processing pipeline supports atomic coordination of input progress, output, and relevant state within its documented boundary.
- A business update and its deduplication record can commit together in one database transaction.
- An external provider supports durable idempotency keys with a retention window that covers your retry policy, allowing you to target one effect despite repeated requests.
A worked example
Retry-safe credits over an at-least-once queue
Suppose a credits service receives 10,000 account-credit events per minute, each adding $5. A worker commits a credit, then crashes before acknowledging the message. At-least-once delivery correctly sends it again, but a naive consumer adds another $5. Instead, each event carries a stable credit ID. In one database transaction, the consumer inserts that ID under a unique constraint and updates the balance only if the insert succeeds. It acknowledges after commit. A replay finds the existing ID and does nothing. This provides exactly-once credit effects within that database, not exactly-once worker execution. A separate email notification still needs its own duplicate-handling strategy.
In the interview
- Say what must happen once: message delivery, a ledger posting, an inventory reservation, or an aggregate update. Avoid an unqualified promise that the entire system is exactly-once.
- Walk through a crash after the side effect commits but before acknowledgment. Explain how the next worker determines whether to repeat, skip, or reconcile the operation.
- Show the atomic boundary. For a database consumer, put the unique operation ID and business mutation in the same transaction, then acknowledge after commit.
- Expect questions about concurrent duplicates, deduplication retention, manual replay, and stable IDs across producer retries.
- For external calls, explain uncertain outcomes. A timeout does not prove failure; reuse the idempotency key, query status when available, and reconcile unresolved operations.
Common mistakes
- Treating exactly-once as a promise that worker code executes only once, rather than a scoped guarantee about committed effects.
- Writing the deduplication marker separately from the business update, leaving a crash window that either loses work or repeats the effect.
- Assuming a broker's exactly-once feature covers external API calls or all downstream databases.
- Claiming at-least-once means eventual successful processing regardless of retention, retry limits, poison messages, or unresolved dead-letter messages.
Where it comes up
Interview questions where choosing between At-least-once and Exactly-once comes up.
- Design a payment systemRetry-safe charges require stable operation IDs, atomic local records, and explicit handling of uncertain provider outcomes.
- Design a distributed message queue like RabbitMQVisibility leases and acknowledgments create duplicate deliveries that consumers must handle safely.
- Design an ad click aggregatorDuplicate delivery and replay must not inflate aggregates used for billing.
- Design a notification systemDurable retries improve delivery reliability but can repeat provider requests unless each channel handles duplicates.
- Design a distributed message log like KafkaConsumer progress and output commits must be coordinated to avoid lost or repeated effects during recovery.
- Design a distributed job schedulerLease expiry and worker crashes can execute the same scheduled occurrence more than once.
Questions people ask
What is the difference between at-least-once and exactly-once?
At-least-once delivery permits duplicates so unacknowledged work can be retried. Exactly-once semantics ensure one committed effect per logical operation within a stated boundary. Always ask whether the guarantee covers broker records, processing state, a database, or an external action.
Can at-least-once delivery provide exactly-once processing?
It can provide exactly-once effects when consumers atomically deduplicate operations and commit their changes. The handler may still execute multiple times. Stable operation IDs, concurrent duplicate handling, and sufficient deduplication retention are essential.
Does Kafka exactly-once prevent duplicate payments or emails?
Not by itself. Kafka transactions can coordinate consumed offsets and records written to Kafka, but an external payment or email call is outside that transaction. Use destination-supported idempotency where available, and define how uncertain outcomes are resolved.