Intro
As part of my assignments as tech advisor and Fractional CTO I have to evaluate technology stacks and advise on tech strategy. There is usually never a one size fits all solution. It always depends. Except for PostgreSQL, but that’s a different story (I am joking of course…).
When it comes to microservices we should trust what Martin Fowler recommends: “One reasonable argument we’ve heard is that you shouldn’t start with a microservices architecture. Instead begin with a monolith, keep it modular, and split it into microservices once the monolith becomes a problem.”
This quote resonates deeply with me. Modular monolith is a very down to the earth approach that strikes the balance between the simplicity of monolithic applications and the flexibility of microservices.
You might also be interested in the following two posts related to this topic:
- A comparison between microservices and monoliths
- A recommendation on how to structure your modular monolith on code level
What Are Modular Monoliths?
A modular monolith is an architectural pattern that is increasingly gaining traction in the software development community. At its core, it is an monolithic applications organized into independent, well-defined modules or packages. It is heavily based on domain-driven design principles.
This structure allows to maintain the simplicity and ease of deployment associated with traditional monoliths while offering the scalability and flexibility of microservices.
Why Are Modular Monoliths Gaining Popularity?
Modular monoliths stand out because they offer a balanced approach to application architecture. Here’s what sets them apart:
Simplicity and Flexibility: Unlike microservices, which can become complex due to their distributed nature, modular monoliths retain a straightforward architecture. This makes development and maintenance simpler.
Independent Modules/Packages: Although deployed as a single application, modular monoliths are composed of independent modules or packages. This depends on your language mostly. This design ensures loose coupling and high cohesion, allowing each module to be developed and tested independently. Changes in one module have minimal impact on others, reducing the risk of system-wide failures.
Scalability Potential: While the initial setup is as a monolithic application, the architecture supports scalability through future refactoring, making it easier to transition to microservices if the need arises.
Advantages of Modular Monoliths
Simplified Complexity: The straightforward architecture of modular monoliths makes them easier to build and maintain compared to microservices, which require managing multiple services and their interactions.
Improved Performance: With a single-process architecture, communication between modules is rapid, enhancing overall system performance. No need for slow and error prone http communication.
Enhanced Data Consistency: The centralized data management approach simplifies transaction handling, ensuring data consistency across modules.
Simpler Deployment Pipelines: Having fewer cross-service dependencies and a single deployable unit simplifies the deployment process compared to microservices, which often require complex orchestration.
Challenges of Modular Monoliths
Despite their advantages, modular monoliths are not without challenges:
Risk of Tight Coupling: Without careful design, modules can become entangled, reducing the system’s modularity and increasing maintenance difficulties.
Scaling Challenges: Although simpler to develop, modular monoliths can be harder to scale compared to microservices, particularly when considering distributed computing features like caching and session management.
Conclusion
Martin Fowler’s advice highlights the pragmatic value of starting with a modular monolith, especially for projects where simplicity and maintainability are priorities. Modular monoliths offer a compelling middle ground, providing a scalable and flexible architecture without the initial complexity of microservices. For many developers, they represent a strategic choice that caters to both immediate project needs and future growth potential.
By embracing modular monoliths, you set your project on a path that combines the best of both worlds—ensuring your application is robust, maintainable, and ready for scalability as your needs evolve.