The Empire, Long Divided, Must Unite; Long United, Must Divide
Coming from the novel “Romance of the Three Kingdoms”, this fundamental principle effectively illustrates the challenges inherent in both centralized and decentralized architectural approaches.
In the following, I will delve into the advantages, disadvantages, and potential drawbacks of adopting monoliths, moduliths, and microservices.
Monoliths
Before application modernization (or digitalization, as you may call it), software was mostly built in a monolithic way. All features are developed and integrated within a single codebase and then deployed as a single unit. All the business data is kept in a single database. While the single application is further split into presentation, service, and persistence layers, they are still closely interconnected within the monolithic structure.
Moduliths
Moduliths lie between monoliths and microservices. While moduliths still maintain a single codebase and a deployment unit, the code is actually modularized and loosely coupled. All the integrations must go through well-defined interfaces. Shared modules are extracted to facilitate code reuse.
Microservices
Microservices is the most distributed representation on the spectrum. In addition to the loosely coupled and well-defined interfaces, microservices physically split the modules into separate deployable units. Each microservice has its own database, is responsible for a business capability and interconnected through RESTful web services, messaging, gRPC, etc.
Monoliths and Moduliths are Effective When You Start Small
When you only start to develop your product, packing everything into a single unit can free you from handling distributed transactions, deployment complexity, traceability, and reducing potential attack surface.
However, when the complexity grows, horizontal scalability for independent modules, and tightly coupled release steps could significantly impact your application’s service level. Without physical boundaries, violation by taking shortcuts in module dependency could lead to the technical debt and eventually become the big ball of mud.
Microservices are Complex to Handle
Adopting a microservice architecture introduces additional challenges that do not typically arise in monoliths. For example:
- Service or event mesh to coordinate service calls among microservices.
- SAGA patterns to handle transactions across microservices.
- Building data projection views to support complex queries with CQRS and event sourcing patterns.
- OpenTelemetry to capture the distributed spans, traces and context propagation. Automation of infrastructure handling through Infrastructure as Code (IaC).
How Should You Choose?
There are no one-size-fits-all rules. Some factors you may consider:
- Application Complexity: Over-engineer is waste of efforts if complexity is not going to happen.
- Team Size and Skillset: Handling asynchronous and distributed service integrations may be overwhelming without sufficient experience. Instead, efforts on deployment coordination may be less critical for small teams.
- Proven Business Value: Prove the business value before heavily investing time and effort into microservices.
Top comments (0)