01Definition
What makes a monolith modular?
A big monolith and a modular one can have the same deployment shape. The difference is what the code is allowed to do. In a modular monolith each module has a public surface, private internals and its own tables. Another module cannot reach in.
That is the same discipline monolith to microservices work needs first, without the network between the parts. Many teams stop here and never need the next step. Others use it as the safe half of a split.
02Boundary rules
Five rules that make a boundary real
If a rule is not checked in the build, it will be broken within a quarter. Write these down, then automate each one.
- Public API per module. One package or interface that other modules may call. Everything else is private.
- Data ownership. A module reads and writes its own tables. No joins across module tables, no shared entities.
- One-way dependencies. Module A may depend on B, or B on A, never both. Cycles mean the boundary is in the wrong place.
- Events for side effects. When module A needs to tell B something happened, publish an event instead of calling B directly.
- Tests per module. Each module can start and be tested without loading the whole application.
03Tooling
How does Spring Modulith enforce the boundaries?
Spring Modulith is a Spring project for building modular applications on Spring Boot 3. By convention, each direct sub-package of your application's main package is a module. Types in that top-level package are the module's public API. Types in nested packages are internal.
From there it gives you four checks you can run in CI:
- A verification call,
ApplicationModules.of(Application.class).verify(), which fails the build on a cyclic dependency or on code that reaches into another module's internal package. - Explicit dependency lists with
@ApplicationModule(allowedDependencies = ...), so a module can use just the modules you named. - Module-scoped integration tests with
@ApplicationModuleTest, which load one module and its declared dependencies. - Generated module diagrams and documentation from the same model, so the picture cannot drift from the code.
04Decision rule
Modular monolith or microservices?
Pick by constraint, not by fashion. The table lists the constraint that should push you one way or the other.
| Constraint | Stay modular | Split to services |
|---|---|---|
| Team size | One team or a few, who talk daily | Many teams that need to ship independently |
| Release cadence | One cadence is fine | A module needs to release many times a day while others do not |
| Scaling | Load grows evenly | One module needs a very different scale or hardware |
| Data consistency | You need ACID across modules | You can accept eventual consistency and sagas |
| Domain clarity | Boundaries are still shifting | Boundaries have held for several releases |
| Operations skill | No platform team yet | Platform team can run many services |
05Next step
When should a module leave the monolith?
Treat extraction as something a module earns. Look for these signals, and extract one module at a time.
06Getting there
How do you find module boundaries in an existing monolith?
- 01
List every database table and note which code reads and writes it. Tables written by one area of code hint at a module. Tables written by many hint at a hidden coupling.
- 02
Group the code by business capability, such as billing or catalog, not by technical layer. A controller-service-repository folder tree is not a module structure.
- 03
Draw the dependency graph from the real imports. Count the cycles. Fewer cycles means a cleaner cut.
- 04
Pick the module with the fewest inbound dependencies and move it behind an interface first.
- 05
Turn on the boundary check in CI for that one module. Expand one module at a time.
07How Ace8 helps
How Ace8 helps with the boundary work
Ace8 is the AI-assisted application modernization practice of AceMQ. We map table ownership and dependency cycles from your code, propose module boundaries, and have engineers review every move. AI-assisted tools handle the mechanical refactoring.
If you are deciding between staying modular and splitting, start with the modernization assessment. It scores each capability against the table above and gives you an order.