Tech Hub

Messaging Options

Choosing the right message for the job

All of the previous is not to say that one size fits all. When designing a reactive microservice system, you want to choose the best messaging pattern for the purpose. To analyze message needs, it is helpful to categorize the contents as queries, commands, or facts:

  • Queries often require a response in timely fashion. For example, Fred uses an ATM to find the balance on his checking account. He expects a response and if he doesn’t receive one, he wants to know why. Synchronous messaging meets this objective.
  • Commands are requests for another service to do something, where the requestor usually needs an answer or an acknowledgement. For example, Fred initiates an ATM withdrawal of one hundred dollars from his checking account. He wants his money now, and if it isn’t forthcoming, he again wants to know why. A slightly different case might be when Fred changes his PIN number online, he needs to know whether it succeeded. Both of these use cases also motivate some type of synchronous communication.
  • Events carry or represent historical facts that cannot be changed. Asynchronous messaging is the most efficient and robust way to communicate them. To continue our example, when Fred receives his money, it is a fact that he withdrew one hundred dollars from his checking account. He can redeposit the money, spend it or lose it, but that doesn’t change the withdrawal event.
Query Command Event

Asynchronous messaging provides a simple scalable pattern that you should take advantage of whenever possible. However, synchronous messaging can — and should — be accomplished as efficiently as possible. For example, the sender might wait for a simple acknowledgement from the receiver and continue its work, expecting a reply from the receiver with the answer at some future point. This requires acceptance that it is OK for the system to achieve a consistent state eventually, rather than immediately, as described in Events and Eventual Consistency.

At the system level, Reactive Microservices should be mobile and addressable to keep communication flowing in spite of failures. You should be able to deploy instances of a particular microservice on any available node. When the number of instances and their locations change dynamically, a level of indirection is necessary to shield clients and other services from what is going on behind the scenes. Service discovery mechanisms meet this need by allowing third parties to find and communicate with a microservice without being aware of how many instances are running or where they are running.

With this introduction to events, eventual consistency, and messaging, it’s time to address the elephant in the room, management of state — in particular — persistence. With a variety of microservices handling what used to be contained within one monolith writing to one database, how can you persist state safely without throttling performance or risking unavailability?

Next Up → Persistence

Learn more

In under 15 minutes:

In less than an hour:

Really dig in: