I think what the article is doing wrong is treating all microservices the same.
Microservices can be split into at least 3 different groups:
- infrastructure (auth, messaging, storage etc.)
- domain-specific business logic (user, orders)
- orchestration (when a scenario requires coordination between different domains)
If we split it like this, it's evident that: - orchestration microservices should only call business logic microservices
- business logic microservices can only call infrastructure microservices
- infra microservices are the smallest building blocks and should not call anything else
This avoids circular dependencies, decreases the height of the tree to 3 in most cases, and also allows to "break" the rule #2 in the article, because come on, no one is going to write several versions of auth just to make it a polytree.It also becomes clearer what a microservice should focus on when it comes to resilience/fault tolerance in a distributed environment:
- infra microservices must be most resilient to failure, because everyone depends on them
- orchestration microservices should focus on compensating logic (compensating transactions/sagas)
- business logic microservices focus on business logic and its correctness
Yeah, as a rule of thumb, this is a considerably better abstraction. Unfortunately it's hard to keep a strong separation between orchestration and business logic in practice, and harder still to ensure the separation stays there over time.