LIGHT

  • News
  • Docs
  • Community
  • Reddit
  • GitHub

Modular Monolith

For some people microservices is “the next big thing”, whereas for others it’s simply a lightweight evolution of the big service-oriented architectures that we saw 10 years ago “done right”. Microservices is by no means a silver bullet though, and the design thinking required to create a good microservices architecture is the same as that needed to create a well structured monolith. And this begs the question that if you can’t build a well-structured monolith, what makes you think microservices is the answer?

If it is not designed correctly, microservices is also known as a distributed big ball of mud. And people always assume that all monoliths are big balls of mud.

MSAs, like any distributed application architecture, involve increased complexity and costs; table stakes, if you will. Like an iceberg, there’s both a lot more to it than just what’s showing above the waterline and a fair amount of hazard for the unwary. If a development team cannot or will not comply with design guidelines (e.g. modularity requirements), injecting additional complexity is probably not the solution you need.

Distributing an application makes it harder to accidentally entangle different concerns, but it doesn’t make it impossible.

I’d argue that making it harder to accidentally break modularity addresses neither of the groups I mentioned earlier: those that cannot or will not comply. It’s ironic, but those who fail to understand the need for modularity can be very creative in their “solutions”, regardless of the obstacles. In short, distribution as a means of “ensuring” modularity fails the fitness for purpose test.

The situation becomes worse when you factor in the additional complexity inherent in a distributed system. Likewise, there’s the cost of the table stakes (infrastructure, process, staffing, etc.) mentioned above. Of course, having abandoned the principle of cause and effect, one could attempt some “creative” workarounds to avoid having to pay the price (in other words, adding more and more complexity).

When you introduce significant additional complexity (with all its attendant risk) with little chance of the technique actually achieving its goal, you’ve caused harm.

Why are microservices useful?

Microservices are useful because of two things:

  • scale up the team very quickly by taking advantage of Conway’s Law

  • modular development

In addition, microservices can scale very easily and minimize spending on the cloud. The reason is that when load increases, more specific instances can be started at a minimal cost.

As we can see from the industry examples, these criteria apply very well for large projects that need to scale quickly. So if you need to start such a project, by all means, use microservices. But if you don’t need to scale that quickly, there are easier ways. The reason is that microservices, like any architectural approach, are a trade-off.

A downside and a huge mistake

Microservices have one important downside and can lead to one huge architecture mistake.

The downside is that microservices architecture leads to huge complexity increases for deployment and operations. Deploying one monolith is very different from deploying 100 or 1000 separate services. Monitoring and debugging then becomes a very difficult job. There are solutions, but each adds to costs and complexity. This investment might not pay off for smaller products.

The architecture mistake is to create microservices that directly depend on other microservices. This is just a re-creation of the dependency hell problem in deployment. If dependencies are hierarchical, changing a service propagates and requires a lot of redeployments. Instead, aim for services that completely encapsulate one atomic change. This is the hardest thing to do about microservices; no wonder it took Fred George’s team weeks to figure it out (and probably a lot more time after starting the development).

Modular monolith

There is an alternative to microservices, one that we used successfully for light-hybrid-4j: the modular monolith.

Can we realize the benefit of microservices and still enjoy the simplicity of monolith? The answer is the modular monolith. It is an architecture sitting in between monolith and microservices. Instead of a big black box of the monolith, we apply microservices principles to vertically slice the application to multiple independent services; however, we don’t want to deploy these services distributed in the first place but put them together so that the communication is in-process instead of HTTP or other network protocol. This removes the complex topology of microservices and hugo front infrastructure cost. And it leaves the room to scale these services individually if the load is heavy.

In JVM, this means we have several independent services deployed into the same JVM whether or not they are in the same container or virtual machine.

light-hybrid-4j framework is designed to be a modular monolith or microservices framework. Developers can build services just like the normal microservices with the final output a jar file. Several jar files can be deployed to the same docker container volume and loaded into the same JVM. The communication between these services are through well defined interface contracts and all the details for each service is hidden. If one or more services are getting too much load, then you can put these services into separate containers to scale them only.

  • About Light
    • Overview
    • Testimonials
    • What is Light
    • Features
    • Principles
    • Benefits
    • Roadmap
    • Community
    • Articles
    • Videos
    • License
    • Why Light Platform
  • Getting Started
    • Get Started Overview
    • Environment
    • Light Codegen Tool
    • Light Rest 4j
    • Light Tram 4j
    • Light Graphql 4j
    • Light Hybrid 4j
    • Light Eventuate 4j
    • Light Oauth2
    • Light Portal Service
    • Light Proxy Server
    • Light Router Server
    • Light Config Server
    • Light Saga 4j
    • Light Session 4j
    • Webserver
    • Websocket
    • Spring Boot Servlet
  • Architecture
    • Architecture Overview
    • API Category
    • API Gateway
    • Architecture Patterns
    • CQRS
    • Eco System
    • Event Sourcing
    • Fail Fast vs Fail Slow
    • Integration Patterns
    • JavaEE declining
    • Key Distribution
    • Microservices Architecture
    • Microservices Monitoring
    • Microservices Security
    • Microservices Traceability
    • Modular Monolith
    • Platform Ecosystem
    • Plugin Architecture
    • Scalability and Performance
    • Serverless
    • Service Collaboration
    • Service Mesh
    • SOA
    • Spring is bloated
    • Stages of API Adoption
    • Transaction Management
    • Microservices Cross-cutting Concerns Options
    • Service Mesh Plus
    • Service Discovery
  • Design
    • Design Overview
    • Design First vs Code First
    • Desgin Pattern
    • Service Evolution
    • Consumer Contract and Consumer Driven Contract
    • Handling Partial Failure
    • Idempotency
    • Server Life Cycle
    • Environment Segregation
    • Database
    • Decomposition Patterns
    • Http2
    • Test Driven
    • Multi-Tenancy
    • Why check token expiration
    • WebServices to Microservices
  • Cross-Cutting Concerns
    • Concerns Overview
  • API Styles
    • Light-4j for absolute performance
    • Style Overview
    • Distributed session on IMDG
    • Hybrid Serverless Modularized Monolithic
    • Kafka - Event Sourcing and CQRS
    • REST - Representational state transfer
    • Web Server with Light
    • Websocket with Light
    • Spring Boot Integration
    • Single Page Application
    • GraphQL - A query language for your API
    • Light IBM MQ
    • Light AWS Lambda
    • Chaos Monkey
  • Infrastructure Services
    • Service Overview
    • Light Proxy
    • Light Mesh
    • Light Router
    • Light Portal
    • Messaging Infrastructure
    • Centralized Logging
    • COVID-19
    • Light OAuth2
    • Metrics and Alerts
    • Config Server
    • Tokenization
    • Light Controller
  • Tool Chain
    • Tool Chain Overview
  • Utility Library
  • Service Consumer
    • Service Consumer
  • Development
    • Development Overview
  • Deployment
    • Deployment Overview
    • Frontend Backend
    • Linux Service
    • Windows Service
    • Install Eventuate on Windows
    • Secure API
    • Client vs light-router
    • Memory Limit
    • Deploy to Kubernetes
  • Benchmark
    • Benchmark Overview
  • Tutorial
    • Tutorial Overview
  • Troubleshooting
    • Troubleshoot
  • FAQ
    • FAQ Overview
  • Milestones
  • Contribute
    • Contribute to Light
    • Development
    • Documentation
    • Example
    • Tutorial
“Modular Monolith” was last updated: April 5, 2021: Issue246 (#256) (50b1c10)
Improve this page
  • News
  • Docs
  • Community
  • Reddit
  • GitHub
  • About Light
  • Getting Started
  • Architecture
  • Design
  • Cross-Cutting Concerns
  • API Styles
  • Infrastructure Services
  • Tool Chain
  • Utility Library
  • Service Consumer
  • Development
  • Deployment
  • Benchmark
  • Tutorial
  • Troubleshooting
  • FAQ
  • Milestones
  • Contribute