Free — no signup required

The Modular Monolith: The Organized Middle Ground

2 min read

Cleaning Up the Mess

A monolith does not have to be a mess. The problem with most monoliths is not that they are a single deployable unit — it is that they have no internal discipline. Code calls code across domain boundaries freely, and the database becomes a shared dumping ground.

A Modular Monolith is an architectural style where the application is still a single deployable unit, but internally it is strictly organized into distinct, independent modules based on business domains — for example, a payments module, a shipping module, and an inventory module.

Boundaries Are the Point

The defining characteristic is strictly enforced module boundaries. This is not just a folder structure convention — it is enforced by the build system or language tooling.

  • Code in the shipping module cannot import internal classes from the payments module. It must call a defined public interface (a function or interface that the payments module explicitly exposes).
  • The shipping module cannot run a SQL JOIN against the payments module's database tables. Each module owns its schema. Cross-module data access must go through the module's public API.

In Java, this can be enforced with the Java Platform Module System (JPMS) or tools like ArchUnit. In .NET, it is enforced with project-level boundaries. In Python, it is enforced by convention and linting rules.

Why This Matters

The modular monolith gives you the organizational benefits of microservices — clear ownership, independent development, enforced boundaries — without the operational complexity of managing a distributed system. There are no network calls between modules, no distributed transactions, no service discovery, no separate deployment pipelines.

Critically, if a specific module later needs to scale independently or be owned by a separate team, it is straightforward to extract it into a standalone microservice. The hard work of defining the boundary has already been done. Extracting a module from a well-structured modular monolith is a planned refactor. Extracting a component from a Big Ball of Mud monolith is open-heart surgery.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free