First an Apology...
This is a public apology to my friend Brandon @flybayer. Back in 2020 when he published Blitz, I replied to one of his tweets with something along the lines of:
"I don't understand why people want to go back to the monolith, especially on top of React, I thought we have gone past that and microservices + SPAs are the norm today".
I was wrong, very wrong...
Is There a Middle Ground?
I have been exploring a lot of the new cool stuff that is coming to the JavaScript ecosystem lately, and I have noticed an interesting trend: developers want the flexibility and scalability of modular systems but without the maintenance and complexity overhead that it brings.
This is where backend tools like MicroLib
and Full Stack "meta-frameworks" like Blitz
and Remix
promise to bring back the "good old productivity win" of monolithic frameworks like Ruby on Rails but keeping the modularity and component first approach of the modern web.
Modular Monoliths
This concept is not new and probably not very popular these days; It is an architectural style where you build applications in a modular fashion by enforcing strict boundaries between different domains and improving code reusability which makes code organization and dependency management easier. The key to a Modular monolith is that you keep the parts (modules) that compose the system as a single deploying unit, aka "monolith".
Why Would Anybody Use This?
Being the middle ground between a traditional monolith and a full-blown microservices architecture, a modular monolith only brings limited benefits in terms of scalability, autonomous teams, and independent delivery, however, it could be a better approach than starting with microservices from day one. This follows the advice of Martin Fowler in his article "Monolith First".
The modular monolith could be implemented as a way of identifying the boundaries of the system while keeping the agility and low maintenance overhead of a monolith in order to increase development speed and quicker time to market.
This path could lead to an initial design of the system and serve as an intermediate state that can be sliced into individual microservices in the future, however, if the team already has the experience and are comfortable with microservices, there are clear system boundaries from day one and the infrastructure is already in place, then going straight to microservices should be considered instead.
New Generation Modular Monoliths
How are the new full stack "meta-frameworks" like blitz.js
(built on top of next.js) the new generation of modular monoliths?
The way a framework like Blitz
works is by keeping the frontend separate in a Single Page Application fashion but connecting to the data layer without the use of REST/GraphQL APIs allowing for direct database access. It remains as a single deploying unit, however, it has clear boundaries that can be "peeled off" and moved to separate APIs like microservices or serverless functions in the future.
Hexagons, Hexagons Everywhere!
If you want to keep your frontend and backends separate but you don't want to pay the "microservices premium", another interesting pattern that has emerged is libraries like "MicroLib", built on top of Module Federation and based on "hexagonal architecture" to create a "polylith", a monolith comprised of multiple (what would otherwise be) microservices.
The key difference with a traditional "modular monolith" is that a "polylith" can independently deploy the multiple modules that comprise the system. This could be the "best of both worlds" in terms of manageability, reusability, and autonomy.
Conclusion
Senior Engineers learned the phrase "it depends" from Architects... so should you implement a modular monolith? Well, it depends on your requirements and where you are in the lifecycle of your application. Big companies like Shopify have successfully scaled their monoliths by implementing a modular monolith and prove that the answer is not always microservices.