As identigral has mentioned in the comments, "There's no One True Way to implement microservices".
I'm pretty new to the microservices architecture myself but here's some advice I can offer.
Avoid synchronous service-to-service calls when possible
One of the biggest benefits of the microservice architecture is that your application is composed of several small-ish loosely coupled services. This is a benefit because it makes maintenance easier. You can work on a microservice in relative isolation knowing that it is very unlikely you'll affect the larger ecosystem (as long as you don't change that microservice's public contract).
When you make direct service-to-service calls you tighten the coupling between those services and loose this benefit.
Know which services own which entities
You mentioned populating Product
s with User
data when Product
and User
are actually owned by two different microservices.
Rather than duplicating the User
information in two services, it might make more sense for the Product
service to only store the subset of User
information it needs for its own purposes.
For this to work, the Product
service needs to understand that the User
service is the owner of that User
data. This means that changes to the User
information should always come from the User
service. The Product
service, if it is interested in those changes, should subscribe to events from the User
service and update its local copies as needed. I believe this approach is called "Eventually Consistent" and is a decent compromise to avoid forcing two microservices to be coupled by synchronous API calls and to avoid sharing ownership of data.
Be careful about your service boundaries
I think this is arguably the most difficult aspect of microservices. If your microservices are too large they can become mini-monoliths that are responsible for too many things and become difficult to maintain over time.
Conversely, if your microservices are too small, they just become thin views over data and defining behaviour over that data ends up being distributed awkwardly over multiple services.
Looking at your examples, I worry that you've gone down the route of making your services too small.
What I've found helpful in dealing with this is Domain Driven Design's concept of Bounded Context. In DDD, when modelling your application and its domain, you're encouraged to draw a map of all the main concepts and try to identify relatively isolated regions of data and behaviour. These relatively isolated regions are Bounded Contexts (BC) and tend to map really well to microservices.
Additionally, DDD talks about how multiple BC can have different versions of the same concept (eg, User
) without actually being duplicated data.
I'm still learning DDD but it's been a very helpful tool in navigating my first attempt at the microservice architecture. I'd recommend reading up on it.
This question is more about "make sure" that this is the right way , based on what I understood or seeking for more advanced users to give a suggestion.
Other people's experience is helpful when they can resolve specific doubts about specific dead ends. However, the here question boils down to "What's the right way to handle IPC in MS architectures"?You can't invest time effectively if you are not sure what you are reading
. The only way to be sure you got something correct is through trial and error. Otherwise, you are just echoing other's opinions. That won't help you.