Skip to main content

Asynchronous Messaging


Messaging is a key strategy employed in many distributed environments such as the cloud. It enables applications and services to communicate and cooperate, and can help to build scalable and resilient solutions. Messaging supports asynchronous operations, enabling you to decouple a process that consumes a service from the process that implements the service.

At the heart of messaging is the message queue, which acts as a buffer that supports send and receive operations. A sender constructs a message in an agreed format and posts the message to a queue. A receiver retrieves the message from the queue and processes it. If a receiver attempts to retrieve a message from an empty queue, the receiver may be blocked until a new message arrives on that queue. Many message queues enable a receiver to query the current length of a queue or peek to see whether one or messages are available, enabling the receiver to avoid being blocked if the queue is empty.

The infrastructure that implements a queue is responsible for ensuring that once a message has been successfully posted, it will not be lost. By default, senders compete for messages, and no two senders should be able to retrieve the same message simultaneously. Retrieving a message is normally a destructive operation - when a message is retrieved, it is removed from the queue. However, a message queue may also support message peeking. This is a nondestructive receive operation that retrieves a copy of a message from the queue but leaves the original message on the queue. This mechanism can be useful if several receivers are retrieving messages from the same queue, but each receiver only wishes to handle specific messages. The receiver can examine the message it has peeked and decide whether to retrieve the message (which removes it from the queue) or leave it on the queue for another receiver to handle.

In addition to these basic concepts, there are several common message queuing patterns that can be used to build scalable and reliable distributed systems:

One-way messaging: In this pattern, the sender simply posts a message to the queue in the expectation that a receiver will retrieve it and process it at some point.

Request/response messaging: In this pattern, a sender posts a message to a queue and expects a response from the receiver. You can use this pattern to implement a reliable system where you must confirm that a message has been received and processed. If the response is not delivered within a reasonable interval, the sender can either send the message again or handle the situation as a timeout or failure. This pattern usually requires a separate communications channel in the form of a dedicated message queue to which the receiver can post its response messages (the sender can provide the details of this queue as part of the message that it posts to the receiver).

Broadcast messaging: In this pattern, a sender posts a message to a queue, and multiple receivers can read a copy of the message (receivers do not compete for messages in this scenario). This mechanism can be used to notify receivers that an event has occurred of which they should all be aware and may be used to implement a publisher/subscriber model.

These patterns can be used in various scenarios to achieve different objectives, such as:

  • Decoupling workloads
  • Temporal decoupling
  • Load balancing
  • Load leveling
  • Cross-platform integration
  • Asynchronous workflow
  • Deferred processing
  • Reliable messaging
  • Resilient message handling
  • Non-blocking receivers

However, there are also several considerations to keep in mind when using message queues. For example, the order of messages may not be guaranteed, and there is usually no guarantee over which receiver handles any specific message. Additionally, some message queuing systems guarantee at least once delivery of messages, but it is possible that the same message could be received and processed more than once. Poison messages, or messages that cannot be handled, can also obstruct the processing of other valid messages in the queue, and it is necessary to be able to detect and discard them. Lastly, a message might have a limited lifetime and if it is not processed within this period, it might no longer be relevant and should be discarded.