
Message delivery Guarantees
Introduction
Notifications are an integral part of modern systems—whether it’s an email alert, a push notification, or a message in a chat app. But ensuring that a notification reaches the user reliably isn’t as straightforward as it seems. Depending on the use case, different delivery guarantees come into play.
In this post, I will summarize the three key delivery models: At Most Once, At Least Once, and Exactly Once—what they mean, how they work, and when to use them. This should help you design a robust notification system that meets your business requirements. This is also extensible to other designs that have producer consumer systems.
Why Delivery Guarantees Matter
- Reliability: Users expect to receive important notifications, but not be spammed with duplicates.
- Correctness: In financial or transactional systems, duplicate or lost messages can have serious consequences.
- User Experience: Missed or repeated notifications can confuse users and erode trust.
- Cost: Retries and deduplication add operational complexity and resource usage.
1. At Most Once
“I’ll send it, but I won’t check if you got it.”
In this model, a message is delivered zero or one time—meaning there’s a chance the recipient may never receive it. Once sent, there’s no retry mechanism. If something fails (e.g., a network issue), the message is lost forever.
How It Works
- The sender transmits the message and does not wait for an acknowledgment (ACK).
- No retry logic or persistence.
- If the message is lost in transit, it is not resent.
Sender --(message)--> Receiver
(no ACK, no retry)
Use Cases
- Non-critical notifications like promotional emails or updates
- Telemetry data where occasional loss is acceptable
- Real-time stock price updates (where old data becomes irrelevant)
- Logging and analytics events
Implementation
- Messages are sent without acknowledgment (ACK) from the receiver.
- No retry logic or persistence.
- Low latency but unreliable.
TIP
Think of it like a one-way broadcast—whoever gets it, gets it!
Real-World Example
- UDP protocol in networking (no guarantee of delivery)
- Push notifications for marketing campaigns
2. At Least Once
“I’ll keep sending it until I’m sure you got it.”
Here, a message is delivered at least once, but it may arrive multiple times. The sender ensures delivery by retransmitting until it gets an acknowledgment (ACK) from the receiver. However, if the ACK gets lost in transit, the sender may resend the message even though the receiver already got it—resulting in duplicates. Depending on the system, duplicates can be handled.
How It Works
- Sender transmits the message and waits for an ACK.
- If no ACK is received within a timeout, the sender retries.
- The receiver may receive the same message multiple times.
Sender --(message)--> Receiver
<---(ACK)---
(retry if no ACK)
Use Cases
- Payment transactions notification to users (where it's better to notify user to do payment twice than miss a payment), Payment should be processed once though
- Order confirmations in e-commerce (as long as duplication is handled)
- Critical alerts (e.g., fraud detection notifications)
- Emails, SMS notifications (some providers retry if not acknowledged).
Implementation
- The sender retries until ACK is received.
- The receiver needs idempotency handling to avoid processing the same message multiple times.
- Reliable but may cause duplication.
Idempotency Example
Suppose a payment notification is sent twice. The receiver should check if it has already processed the notification (using a unique message ID) and ignore duplicates.
Real-World Example
- Email delivery systems (SMTP retries)
- Kafka default delivery guarantee
- SMS gateways with retry logic
TIP
Think of it like a notification system where a user gets multiple email reminders because of retry logic.
3. Exactly Once
“I’ll make sure you get it exactly once, no more, no less.”
This is the most complex and expensive model, where each message is guaranteed to be delivered exactly once with no duplicates. It requires sophisticated mechanisms to track message status and prevent reprocessing. It guarantees no loss or duplication but comes with higher overhead.
How It Works
- Sender transmits the message and waits for an ACK.
- The receiver keeps track of processed message IDs.
- If a duplicate message arrives, the receiver discards it.
- The sender ensures that a message is not resent once acknowledged.
Sender --(message, ID)--> Receiver
<---(ACK, ID)---
Receiver stores processed IDs to avoid duplicates
Use Cases
- Banking transactions (a money transfer should happen only once)
- IoT applications (sensor data should not be duplicated)
- Event-driven systems (where duplicate processing can cause inconsistencies)
- Inventory management (avoid double-decrementing stock)
Implementation
- Deduplication mechanisms ensure the same message isn’t processed twice.
- Requires transactional message queues (like Kafka, RabbitMQ, or AWS SQS FIFO).
- Higher overhead but ensures correctness.
Techniques
- Use unique message IDs and store processed IDs (with TTL to avoid unbounded growth).
- Use transactional queues or logs.
- Two-phase commit or distributed transactions (rare, due to complexity).
Real-World Example
- Kafka with idempotent producers and transactional consumers
- AWS SQS FIFO queues with deduplication
- Payment gateways ensuring single charge per transaction
TIP
Think of it like airline tickets—if you book one seat, you don’t want to be charged twice or have your seat disappear!
Choosing the Right Model: Trade-offs Matter
There’s no one-size-fits-all solution. Your choice depends on:
- Cost & Complexity – Exactly Once is costly; At Most Once is simple.
- Use Case Criticality – Can you tolerate occasional loss? If yes, go for At Most Once.
- Duplicate Handling – If your system can handle duplicates, At Least Once might be a good balance.
- Latency Requirements – More guarantees often mean more latency.
Guarantee | Delivery | Risk | Example Use Case |
---|---|---|---|
At Most Once | 0 or 1 times | Lost messages | Stock price updates |
At Least Once | 1 or more times | Duplicates | Payment notifications |
Exactly Once | Exactly 1 time | High cost | Money transfers |
Diagrams
At Most Once:
Sender --(message)--> Receiver
(no ACK, no retry)
At Least Once:
Sender --(message)--> Receiver
<---(ACK)---
(retry if no ACK)
Exactly Once:
Sender --(message, ID)--> Receiver
<---(ACK, ID)---
Receiver stores processed IDs to avoid duplicates
Best Practices
- Use unique message IDs for deduplication.
- Make consumers idempotent whenever possible.
- Choose the simplest guarantee that meets your business needs.
- Monitor delivery metrics and tune retry/persistence strategies.
- Document the delivery semantics of your APIs and systems.
Final Thoughts
Understanding these delivery guarantees is crucial when designing a scalable and reliable notification system. Each model has its own trade-offs, and the right choice depends on your specific business needs.
Would love to hear your thoughts—what delivery guarantees have you implemented in your systems? 🚀