Message Delivery Guarantees in Push and Pull Systems
In messaging systems, producers and brokers rely on acknowledgments to ensure message persistence and successful delivery.
When a broker pushes a message to a consumer, it waits for an acknowledgment.
This acknowledgment signals the broker to delete the message.
If the acknowledgment does not arrive or delivery fails, the broker may retry immediately or requeue the message for later delivery.
After multiple retries, the broker may apply a fallback: sending the message to a dead letter queue.
A dead letter queue isolates messages that cannot be processed correctly.
Such messages are often called poison pills.
In a pull-based system, the consumer initiates a request to fetch a message.
If the request fails, the consumer retries.
After processing, the consumer sends a confirmation to the broker.
This confirmation is an acknowledgment.
The broker uses this to delete the message.
Deleting a message is not the only option—this alternative will be discussed in the next video.
For now, assume deletion occurs upon successful acknowledgment.
When multiple competing consumers exist, each message must be delivered to only one consumer.
Competing consumers improve processing speed and system reliability through redundancy.
In push-based systems, the broker manages message deletion.
It selects one consumer at random from the group and sends the message.
If delivery fails, the broker attempts to push the message to the same consumer again.
After repeated failures, the broker fails over to a different consumer in the group.
In pull-based systems, all consumers poll for messages.
If one consumer is processing a message, others must not receive it.
To prevent duplication, the broker must mark the message as unavailable.
This state is called visibility timeout.
The broker sets a visibility timeout period.
During this time, no other consumer can access the message.
This period is expected to be sufficient for one consumer to process and delete the message.
AWS SQS implements this visibility timeout mechanism.
It ensures message visibility is maintained during processing.
Now, we introduce message delivery guarantees.
There are three types: at most once, at least once, and exactly once.
At most once means a message is delivered no more than once.
If delivery fails, the system does not retry.
This means the message might be lost.
This guarantee is often described as best-effort semantics.
At least once means the system retries until delivery succeeds.
The message is never lost, but may be processed multiple times.
Exactly once means every message is delivered and processed exactly once.
This is the ideal guarantee.
We always want exactly once delivery.
It ensures no duplication and no loss.
Message Delivery Guarantees: Failure Handling and Semantics
In an ideal system with no failures, each message is processed exactly once. But failures are inevitable.
The way failures are handled defines the delivery guarantee of the system.
At Most One Delivery Guarantee
A messaging system offers at most one delivery guarantee if the broker does not wait for acknowledgment when sending a message to a consumer.
As soon as message bytes are written to the TCP socket, the broker considers delivery complete.
It then removes the message from the queue.
During this process, the message may be lost in transit to the consumer.
The consumer might also fail during processing, resulting in message loss.
This guarantee trades higher throughput for reduced safety.
At Least One Delivery Guarantee
A system offers at least one delivery guarantee if the broker waits for acknowledgment.
Until it receives an acknowledgment, the broker keeps the message in the queue.
In a push-based system, unacknowledged messages are requeued and re-delivered.
In a pull-based system, unacknowledged messages become available when visibility timeouts expire.
In both cases, the consumer may receive the same message multiple times.
Critical Acknowledgment Timing
The consumer must send an acknowledgment only after successfully processing the message.
If acknowledgment is sent before processing, the broker removes the message from the queue.
If message processing fails, there is no mechanism to retry processing.
This behavior results in at most one delivery semantics, not at least one.
Exactly One Delivery Guarantee
Exactly one delivery is achievable.
Examples include Kafka and SQL, which support such guarantees.
This can be achieved through idempotency or distributed transactions.
For idempotency:
-
The broker must be idempotent to detect and eliminate duplicate messages during publication.
-
The consumer must be idempotent to avoid processing the same message more than once.
Systems with exactly one delivery guarantee typically offer lower throughput.
They also introduce complex usage nuances.
Most messaging systems default to at least one delivery guarantee.
This configuration prevents message loss, maintains high throughput, and is easier to implement.
The topic of exactly one processing will be explored in greater detail on my YouTube channel.
Questions
- In a push-based system, what happens if the consumer fails to send an acknowledgment after receiving a message?
- How does a visibility timeout in a pull-based system prevent duplicate message delivery?
- If a consumer sends an acknowledgment before processing a message, what delivery guarantee does this correspond to?
- What is the role of a dead letter queue in message delivery failure scenarios?
- Why might a messaging system default to at least once delivery even though exactly once is ideal?
- Can a system achieve exactly once delivery without both broker and consumer being idempotent?
- What is the trade-off between throughput and message safety in at most once delivery?
- Under what conditions does a broker requeue a message after failed delivery attempts?
Key takeaways
- At most once delivery means a message is never delivered more than once, but may be lost if delivery fails.
- At least once delivery ensures no message is lost, but may result in duplicate processing.
- Exactly once delivery guarantees each message is processed exactly once, achievable via idempotency or distributed transactions.
- In push systems, the broker deletes a message only after receiving an acknowledgment.
- In pull systems, unacknowledged messages remain visible until visibility timeouts expire.
- The consumer must process a message before sending an acknowledgment to ensure at least once semantics.
- Premature acknowledgment causes message deletion and results in at most once behavior, not at least once.
- Most messaging systems default to at least once delivery due to better balance of throughput and reliability.
- Exactly once delivery typically reduces throughput and requires careful configuration and idempotent components.