When you move from monoliths to microservices, and your services aren't 100% isolated from each other, eventually you need your microservices to communicate. They need to expose their capabilities to other applications and systems, and when you get to this point, you need to design their means of communication.
Microservices doesn't prescribe a specific mode of messaging (nor should it), and I personally like the presentation "Messaging and Microservices" (slides) from Clemens Vasters as a great overall primer to the problem space, so start there.
Once we understand the overall landscape of messaging and microservices, the next part is design. How do we design the communication between different services? How do we build the channels so that we maintain high cohesion, low coupling, and ultimately, autonomy for our services? What are some general guidelines and principles for ensuring our success here?
Luckily, the names of things of changed over the years but the rules stay largely the same. For (micro)services-based systems I've run into that haven't been as successful, designing the boundaries and interactions goes a long way into ensuring the success of your overall architecture.
The Entrance Fee - Good Boundaries
Designing microservice boundaries well is our first goal. I often find that when messages are designed poorly, it's simply because the original boundaries weren't designed well. Well-defined microservice boundaries tend to be self-evident, because they achieve the goal of autonomy. Poorly-defined microservice boundaries tend to lose their autonomy, relying on a group of services to actually perform a business goal.
If you have to run a dozen microservices for your service to even run, it's a sign you've chosen the wrong boundaries. Instead of focusing on the nouns in your system (Orders, Customers, Products), you instead should focus on capabilities (Catalog, Checkout). Services that just manage a thing tend to quite data-oriented and RPC-focused. Rather than focusing on tiers, we look at vertical slices that stretch all the way to the front-end.
But once we have those boundaries, how do we actually design the communication between services? In the next few posts, I'll walkthrough designing messages both inside and between services, looking at the benefits and tradeoffs of each approach, as well as some general rules of thumb and patterns that tend to let us fall into the pit of microservice success.