InterviewKata
Software architecture · Level 3: Architecture styles · Module 11 of 46

Layered and modular monolith

Most software ever written is a monolith, and most of it is layered: screens on top, business rules in the middle, data access at the bottom. It's the default for good reasons: simple, cheap and familiar. Its domain-partitioned cousin, the modular monolith, keeps those benefits while organising code around the business, and is many teams' best answer to "should we do microservices?". This module covers both, including how they decay and how to stop it.

See it builtThe Architecture styles track builds these styles for one bike-share app, with code you can run: 01 Monolith and modular monolith · 02 Layered.

1. The idea

A department store versus a shopping centre under one roof. The department store is organised by function: one floor for tills, one for stockrooms, one for displays, and every sale passes through all of them. The shopping centre is organised by shop: each shop has its own till, stockroom and window, and shares only the building, the doors and the car park. Both are one building (one deployment); they differ in how the inside is divided.

Layered (technically partitioned)

The code is split into horizontal layers: presentation, business, persistence and the database. Each layer has one technical job. Layers are usually closed: a request must pass through each layer in turn, never skipping one. That gives layers of isolation: a change in one layer (a new database) doesn't affect the others.

Modular monolith (domain partitioned)

The code is split into business modules (orders, payments, catalogue), each with its own layers inside and a small public API. Modules talk only through those APIs or through in-process events, and ideally each owns its own tables. It's still one deployment and one database server, so it's simple to run, but changes stay inside a module.

Both are one architecture quantum (Module 09): they scale, fail and deploy as a whole. That's their main limit, and also why they're cheap.

How they rate

CharacteristicLayeredModular monolith
Partitioningtechnicaldomain
Quanta11
Cost★★★★★★★★★★
Simplicity★★★★★★★★★★
Scalability★★★★★★★★★★
Elasticity★★★★★★★★★★
Fault tolerance★★★★★★★★★★
Evolvability★★★★★★★★★★
Deployability★★★★★★★★★★
Testability★★★★★★★★★★
Performance★★★★★★★★★★

Our qualitative ratings, 1 to 5 stars, more is better (for cost, more stars = cheaper). They compare styles in general; your context can move any of them.

2. How it works

Closed layers, isolation, and the sinkhole

Two requests travel through the same four layers. Watch what each layer does with them, then a database change, then a common shortcut.

A modular monolith keeping its boundaries

Modules are only as separate as the rules that keep them apart. In one codebase, nothing stops a developer importing another module's internals, except a test. Watch one.

3. Try it yourself

Would the architecture test pass?

Each line is a change someone proposes. Decide whether it respects the structure, then reveal the rule and the kind of automated test that would catch it.

4. Trade-offs

Technical vs domain split

Layers make technical changes (a new UI framework, a new database) local; modules make business changes local. Business changes are far more frequent in most systems, which is why the modular monolith usually ages better.

Closed vs open layers

Closed layers isolate change but force pass-through code. Opening a layer (letting requests skip it) removes the sinkhole but couples the upper layer to the lower one. Open a layer only for a named reason, and record it.

One deployment vs independence

One deployment means one pipeline, easy transactions, in-process calls and simple debugging. It also means one release train and one scaling unit for everything.

Shared vs owned tables

A modular monolith with one shared schema still couples modules through the data. Giving each module its own tables (or schema) costs some joins, and makes later extraction into a service far easier.

5. In real projects

Layered is the starting point of most frameworks. MVC web frameworks produce controllers, services and repositories by default. That's fine for small systems; as they grow, every business change crosses every layer and every team.

The modular monolith is a deliberate choice, not a stepping stone you're ashamed of. Several large, well-known products run as modular monoliths, and tools exist to enforce module boundaries inside one codebase: ArchUnit for Java, Spring Modulith, Packwerk for Ruby, Java's own module system, or plain package-visibility rules.

Agility isn't only for microservices. A well-modularised monolith with good tests and continuous delivery can release many times a day. What hurts agility is poor modularity and slow, risky releases, and those can exist in any style.

Say it in the interview

Two-sentence answers
  • "What's the architecture sinkhole?" Requests that pass through layers that add nothing, just forwarding calls. A little is normal; if most requests do it, the layering is costing more than it gives.
  • "Why a modular monolith instead of microservices?" It keeps changes local by business area, like microservices, without the network, data distribution and operations cost. It's a good default when all parts can share one set of characteristics.
  • "How do you stop a modular monolith decaying?" Each module exposes a small public API and owns its tables, and architecture tests in the build fail if any module reaches into another's internals.
Red flags interviewers notice
  • Calling a monolith "legacy" by definition.
  • Modules that share every table, described as independent.
  • No mechanism to enforce boundaries inside one codebase.

6. Remember it

Memory hook: "Floors or shops"Layers split by technical job (floors of a department store); modules split by business area (shops in a centre). Both share one building.
How this hook works: what "floors or shops" means

What the slogan means, phrase by phrase

"Floors"
Horizontal layers: every sale visits every floor, so most changes visit every layer.
"Shops"
Vertical modules: each shop has its own till and stockroom, so a change stays in one shop.
"one building"
Either way, one deployment: it scales and fails as a whole.

Why this picture fits: it captures the one decision that separates the two styles (the direction of the split) and the property they share (one quantum).

The story → the concept

The buildingThe architecture
Tills floor, stockroom floorPresentation layer, persistence layer
Shops with their own tillsModules with their own layers
Shop doors onto the mallA module's public API
Security guard checking back doorsArchitecture tests in the build

The trap it saves you from

Believing that a monolith must be a big ball of mud, or that modules stay separate without enforcement.

7. Common mistakes

Unenforced boundariesWithout tests, module boundaries erode one "quick import" at a time until the modular monolith is a big ball of mud.
Ignoring the sinkholeWhen most requests just pass through the business layer, the layering is ceremony. Measure it; open a layer deliberately or rethink the structure.
Shared tables everywhereModules joining each other's tables are coupled through the database, whatever the code says.
Layered by habitChoosing layers because the framework generated them, for a system whose changes are mostly business changes across many teams.

8. Design exercise (30 minutes)

  1. Measure the sinkhole (10 min). Pick ten endpoints in a layered system you know. How many have real logic in the business layer?
  2. Draw the modules (10 min). Sketch the same system as a modular monolith: which modules, what each one's public API would be, and which tables it would own.
  3. Write two rules (10 min). Write two architecture-test rules you'd add to the build, in plain English, and what each would have prevented.

9. Self-check quiz

What does it mean for a layer to be closed?

Closed layers give layers of isolation: each layer only knows the one below.

What is the architecture sinkhole?

Some is normal; most requests doing it means the layers cost more than they give.

In a modular monolith, how should Orders get data from Payments?

Internals and tables stay private, so Payments can change them freely.

How many architecture quanta does a modular monolith with one database have?

One deployment and one database: it scales and fails as a whole.

Why does a modular monolith usually age better than a layered one?

Most changes are business changes; domain partitioning keeps them local.

10. Go deeper

ResourceTimeWhy
Fundamentals of Software Architecture, 2nd edition (Richards and Ford)bookThe chapters on the layered and modular monolith styles.
ArchUnit user guide30 minWriting layer and module rules as unit tests (Java; similar tools exist for other languages).
Spring Modulith20 minA framework built around modular monoliths: module APIs, events and verification.