Decision guide
At-Most-Once vs At-Least-Once vs Effectively-Once
What delivery guarantee do you need, and how do you get it?
Side by side
| Criterion | At-most-once | At-least-once | Effectively-once |
|---|---|---|---|
| Duplicates | Never | Possible | Absorbed |
| Message loss | Possible | No (until retries exhausted → DLQ) | No |
| Mechanism | Ack first / fire-and-forget | Ack after processing, retries | Inbox/dedupe, idempotent writes, Kafka EOS |
| Complexity | Lowest | Low | Medium–high |
| External side effects | Maybe lost | Maybe duplicated | Need idempotency keys at destination |
When to choose each
At-most-once
Send/ack before processing; never redeliver.
Choose when
- Metrics and telemetry
- Best-effort notifications
Avoid when
- Business events, payments
At-least-once
Retry until acknowledged; ack after processing.
Choose when
- Most business events and jobs
- Default for brokers
Avoid when
- Consumers that can't tolerate duplicates
Effectively-once
At-least-once delivery + idempotent/deduplicated processing (or transactional pipelines).
Choose when
- Payments, ledgers, inventory
- Stream processing with transactional sinks
Avoid when
- When duplicates are harmless (extra complexity)
Verdict
Assume at-least-once and make consumers idempotent — that yields effectively-once processing. Reserve at-most-once for data you can afford to lose, and remember that broker 'exactly-once' features stop at the broker's boundary.
Learn more
- Messaging, Events and Email Systems
- Idempotency & Retry-Safe Systems
- Messaging & Queues
- Consume Kafka messages with retries and a dead-letter topic (Spring Boot)
- Publish events reliably with the transactional outbox (Spring Boot)