Can Modular Monoliths Outperform Microservices? Exploring Spring Modulith

This article examines how modern modular monoliths, especially Spring Modulith, can provide scalable, low‑overhead alternatives to microservices by isolating modules, reducing remote calls, and simplifying deployment while addressing common concerns about complexity and performance.

21CTO
21CTO
21CTO
Can Modular Monoliths Outperform Microservices? Exploring Spring Modulith
Modern modular monoliths (and Moduliths) are redefining monolithic architecture, offering a hybrid approach that combines the best of both worlds.

Historically, ideas cycle back; what was once discarded often returns stronger. Recently, relational databases have resurged, and monoliths are poised for a comeback, while microservices and serverless are largely driven by cloud vendors seeking more resource sales.

For most use cases, microservices provide limited financial benefit, and scaling them merely distributes costs. A recent technical group discussion highlighted that monoliths, even at massive scale (e.g., Amazon, eBay), face challenges when refactoring large codebases, but they remain a viable option.

Modular Architecture

Developers interested in the next step should explore the Spring Modulith project, which enables building a cohesive system from dynamically isolated modules. This approach separates testing, development, documentation, and dependencies, aiding microservice‑style isolation with minimal overhead.

It eliminates remote calls and duplicated functionality (storage, authentication, etc.). Spring Modulith does not rely on Java Platform Module System (Jigsaw); instead, it enforces separation at test and runtime within a standard Spring Boot project, offering additional observability features.

Example Package Structure

Traditional Spring monolith packages:

com.debugagent.myapp</code>
<code>com.debugagent.myapp.services</code>
<code>com.debugagent.myapp.db</code>
<code>com.debugagent.myapp.rest

With Modulith, the structure becomes more domain‑oriented:

com.debugagent.myapp.customers</code>
<code>com.debugagent.myapp.customers.services</code>
<code>com.debugagent.myapp.customers.db</code>
<code>com.debugagent.myapp.customers.rest</code>
<code>com.debugagent.myapp.invoicing</code>
<code>com.debugagent.myapp.invoicing.services</code>
<code>com.debugagent.myapp.invoicing.db</code>
<code>com.debugagent.myapp.invoicing.rest</code>
<code>com.debugagent.myapp.hr</code>
<code>com.debugagent.myapp.hr.services</code>
<code>com.debugagent.myapp.hr.db</code>
<code>com.debugagent.myapp.hr.rest

This layout mirrors microservice boundaries while keeping a single deployable unit, allowing teams to focus on isolated domains without stepping on each other's toes.

Modules can be annotated to enforce one‑way dependencies (e.g., HR should not depend on invoicing). Events provide fast, transactional decoupling between modules.

Although some microservice tooling (feature flags, messaging) remains applicable, Spring Modulith simplifies deployment and observability, often requiring less infrastructure than full microservice stacks.

Scalability and Performance

Scaling a monolith can be simpler than scaling equivalent microservices because there is only one running instance to replicate. Performance tools can profile the entire system, and fine‑grained caching can eliminate 80‑90% of read I/O, reducing network overhead.

Kubernetes can still be used with monoliths; container images may be larger, but tools like GraalVM mitigate size concerns.

Bottlenecks

Typical monolith bottlenecks include the database, as a single DB can become a performance choke point. However, modern clustering, distributed caches, and specialized databases (e.g., Redis, time‑series stores) can alleviate these limits.

Benefits

Monoliths allow transactions without eventual consistency, simplifying debugging and reducing the complexity of distributed tracing. Network overhead is minimized, and the overall system remains easier to understand and test.

Why Use Microservices?

Microservices gained popularity alongside languages like Python and JavaScript, offering fine‑grained cost control and rapid scaling via Kubernetes. They also enable independent team ownership but can foster siloed development and increased overall system complexity.

Starting with a Monolith

Many experts recommend beginning with a monolith and refactoring to microservices only when necessary. A modular monolith provides a balanced approach, delivering the benefits of isolation without the operational overhead of a full microservice architecture.

For further reading, see the original article by Shai Almog.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backend Architecturesoftware designmodular monolithSpring Modulith
21CTO
Written by

21CTO

21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.