#Microservice Design - Avoiding Tight Coupling

10 messages · Page 1 of 1 (latest)

thorny jackal
#

I have multiple microservices, each responsible for one part of the domain, and each with its own data store. For the sake of example, let's say that's User, Order, Payment and Company. I want these microservices to be loosely coupled, and to reduce direct dependencies between them.

However, I have some complex core business process, order creation for example, that involves all the microservices. The natural thing to do would be to handle order creation within the Order microservice, and make the Order microservice depend on every other microservice. However we have other use cases where the other microservices will have to depend on the order microservice.

My questions are:

  1. Should I even be scared of circular dependencies when dealing with a microservice architecture? Or are they just an unavoidable occurrence?
  2. Let's say I create a separate microservice to handle order creation. Would this microservice have access to the data stores of other microservices? Or would it depend on every other microservice?
  3. Let's say I try managing the order creation process using events instead of direct dependencies. Is it alright if the same microservice handles multiple events for the same business process? How important is being able to replay events? What are some pitfalls I should think about?
gaunt pier
#

About the first solution. Yes you should be scared. You won't achieve any of the benefits of microservices if you couple them.
2) This is a good option to continue with. It shouldn't have access to specific data stores. It should just trigger the next action in the process by calling specific microservice. If the inner microservice needs data from the others to do its job you have to analyze it and maybe pass by the order creation or stor it in the internal store as a cache/copy
3) events or direct call is not an interchangeable decision. You should decide based on the requirements not a guess. So, events doesn't guarantee immediate consistency. You can notice later that your data is inconsistent and you have rollback the order. They are good if you can have eventual consistency but not for strict rules (invariants)

thorny jackal
#

Thanks for the response. So create a separate microservice, and use caching to avoid calls to other services. I'm still curious about when an event based approach could be more relevant. Like, for instance, after order creation, there's a business logic regarding firing notifications and updating statistics which can all be handled with an event. But I'm not sure to what extent events can be utilized before requirements become impossible or too annoying.

#

Could you elaborate on your third point? or do you know any good resources for me to read up on it?

gaunt pier
#

So, all your examples are good for events.
Events won't work in this case:
Your Order service has to check in the Availability whether the product is still available.
You can't just put it in the Order's cache like product_availability and check it because cache can be already invalid and you will sell unavailable product.
You have to call Availability directly, and not just isAvailable? because two concurrent orderders will get that the last product is available and just sell it.
You would need to call block() from both and if it throws (returns maybe 400), then it means it's unavailable.
That's that type of logic that can't work on events and basically you needs an instant consistency of data to make a decision

thorny jackal
#

That's really helpful, thanks!

hazy birch
#

I'd even suggest that availability needs to be checked before an order is put into action. And, when you get that "what if" question at any time in your workflow, you cannot depend on workflow choreography (i.e. where each service fends for itself). You need workflow orchestration, especially if you need to roll-back any part of the process.

In the end, you'll need to ask yourself, is this process so complex or can change so often or needs a clear roll-back should anything fail (i.e. must stay consistent), that choreography will become unwieldy? If the answer is yes, you need a system that will orchestrate the process. It's a central place of failure too (depending on how you do it), but a type of business controller will definitely be necessary. Most people turn to CQRS and in particular SAGAs as the controller of the orchestration. And, with the questions asked above and the answer being a clear "yes" with an order process, I'd suggest you'll need a SAGA orchestrator for sure. 🙂

https://microservices.io/patterns/data/saga.html

#

Although they mention choreography sagas, I'd avoid trying to do them. They are even more unwieldy, as the process grows.

atomic violet
#

Feel the microservices domain layering, should try to ensure that different microservices communicate through the interface layer, this should be no problem, as long as the internal data processing functions do not directly rely on it!

ripe acorn
#

I agree with @hazy birch . SAGAs of some kind might be necessary to cope with the complexity. Event based microservices give you the flexibility to get different services involved. of course, you need to broadcast events at the point other service might be interested in like, orderprocess_started or order_created, user_solvency_positive and so on and so on