we are going through some serious architecture refactor in my system that is still in the design phase.
Today our system has a single server side in NestJS. Instead, we want to use microservices.
I have some questions about microservices architecture best practices:
EDIT: After the answers I got here and a little more research things got more clear to me. One important thing I still would like help with is deciding whether to use orchestrator or choreography in my feedback case. To make my use case more clear - failure in sending mail or in storing the feedback in DB shouldn't make the other operation to fail - they are independent. Now - there are two ways:
What is the better option for this use case?
Common practise is to use a microservice for a dedicated (series) of tasks/responsibility. Storing feedback and sending mail are two such dedicated tasks and could/should be handled by dedicated microservices.
It is recommended to avoid direct dependencies between different services. One service calling another service through for example a REST API is such a dependency. The other service might be not available making your first service unavailable as well (unless you implement some kind of mechanism to handle those circumstances). It also makes it difficult to maintain when the interface of a dependent service changes. This would require you to change the calling service as well.
A possible solution would be to reply on event driven design. Your feedback services stores the feedback in its database and broadcasts an event to inform other interested parties a mail message needs to be send. This event contains everything needed to send the email message. A mail service listening for this event picks it up and handles the message delivery. This way the fact the mail service is offline, is handled by your messaging system in between.
Letting your client call both microservices directly might make things more complicated as well and could potentially create unnecessary network calls between client and backend.
I don't know I understand your remark entirely but sure, there is nothing wrong with using microservices for DB interaction. A lot depends on your intended use to choose one database or another. You could even go one step further and make dedicated services for writing and dedicates services for reading data from databases. Check CQRS for more information about this.
I think you misunderstood something here.
Choreography does not mean one services knows about the other and its interface. Choreography means services talk to each other using events and an intermediate messaging system (a broker if you like). Services 'broadcast' events and other interested services 'listen' for them.
Orchestration puts a certain 'service' or other component in the middle to handle the flow between all involved parties as you pointed out in your diagram.
Whether to choose orchestration or choreography depends on the use case and the complexity of your entire solution. There is no silver bullet to use. One thing to keep in mind maybe, choreography makes it difficult to know who's talking to who when the number of services increase. Orchestration might keep things a bit clearer to understand.
Again, everything depends on the use case, your experience and what you do or don't prefer. Besides the solutions you mention, you could also take a look at AxonIQ Framework/Server or Eventuate. Both of them are event sourcing solutions used in microservice architectures. Bernd Ruecker also blogged some interesting articles about using BPMN engines for microservice orchestration which might be worth looking at.
Additional info after the author's original question edit
Referring to your first diagram. Assuming your mail service is responding to a message sent by your feedback service, this could actually also be considered choreography instead of orchestration.
The idea behind orchestration is to increase de-coupling. To use orchestration, a kind of 'conductor' is placed between the feedback and mail service responding to e.g. a FeedbackStoredEvent
and translation it into SendEMailMessageCommand
. This way, the feedback service is completely unaware of the commands the mail service can receive and the mail services does not know any events sent by the feedback service. Both are completely unaware of each other therefore decoupled. The only party knowing about both, is your orchestrator which is acceptable. If you have to add additional behavior, this is the component to be updated according to your new business case. Important is obviously not to include the 'conductor' logic as a part of your feedback service but as some kind of translator in between... This was not clearly emphasized in my previous response.