Back to the map

Module 11 · Architectural patterns · Lesson 2 of 9

Monoliths

One deployable unit with all the features inside. Why it is the right starting point for most products, how far it scales (further than its reputation), the modular monolith that keeps internal boundaries clean.

IntroShould-knowJunior 10 min Updated Nov 2026

Why it matters

The industry spent a decade treating monoliths as a mistake to be corrected and then spent several years correcting the correction. A monolith is the simplest architecture that can run a real business, and most successful products started as one and many remain one at considerable scale. Knowing how to build a good monolith, and recognising the actual signals that it is time to split, is more valuable than knowing microservices patterns you may never need.

The idea

A monolith is an application built and deployed as a single unit: one codebase, one build, one process (replicated across servers), one database. All features share memory, a transaction boundary and a release. The simplicity is the point: function calls instead of network calls, one schema with joins and transactions across everything, one thing to deploy, debug and monitor.

Clientsmonolith (× N instances)ordersusersbillingcatalogueshared data accessone DB
One deployable containing every module, scaled by running copies behind a load balancer against one database. Internal calls are function calls.

What it gets right

  1. 1

    Transactions and joins across the whole domain

    Creating an order, decrementing stock and recording a ledger entry is one database transaction; the entire Distribution stage of hard problems does not exist yet.
  2. 2

    Refactoring freedom

    Moving code between modules is a rename, not a cross-team API negotiation. Boundaries can be discovered rather than guessed up front.
  3. 3

    Operational simplicity

    One deploy pipeline, one set of logs, one process to profile, one on-call surface. A stack trace shows the whole request.
  4. 4

    Performance

    In-process calls cost nanoseconds; a request that would cross ten services crosses ten functions.

How far it scales

Horizontally, a stateless monolith scales like any application tier: run more copies behind a load balancer, which works until the database is the bottleneck, and the Scaling stage's tools (indexes, caching, replicas, partitioning) push that bottleneck a long way. Shopify, Stack Overflow, Basecamp and GitHub have run or run large monoliths serving enormous traffic. The limits that bite are organisational and operational before they are technical.

The modular monolith

The failure mode of monoliths is not size but the big ball of mud: every module reaching into every other's tables and internals until nothing can change safely. A modular monolith keeps one deployable but enforces internal boundaries: each module owns its tables and exposes an interface, cross-module calls go through that interface (enforced by package visibility or linting), and modules communicate through in-process events where coupling should be loose. The result keeps all the monolith's advantages and makes a later split, if ever needed, a matter of moving a module behind a network boundary it already has.

The real reasons to split

PressureWhat it looks likeDoes splitting help?
Team scaleDozens of engineers blocked on one release train; merge conflicts; fear of deployingYes: independent deploys per team are the strongest argument for services
Divergent scaling or runtime needsOne module needs GPUs or 50 times the instances, or a different languageYes: extract that module
Fault isolationA memory leak in reporting takes down checkoutPartly: bulkheads and separate processes help; services make it explicit
Security or compliance boundaryPayment code must be isolated for PCI scopeYes: a clear boundary reduces audit scope
"It is slow"Latency or throughput problemsUsually no: network hops add latency; fix the database and caching first
"Microservices are modern"No measurable pressureNo

Splitting adds every problem in the Distribution stage: network failures, distributed transactions, data duplication, observability across processes. It is worth paying when the pressures above are real and measured, and wasteful before.

Trade-offs

A monolith buys simplicity, transactional integrity, refactoring freedom and performance, and pays with a single release unit that couples teams, uniform scaling and runtime, and a blast radius that spans features. A modular monolith keeps the first list and softens the second. The honest default for a new product is a modular monolith until a specific pressure justifies extracting a service.

In an interview

Start there and say when you would leave: "A modular monolith with clear module boundaries and one Postgres, scaled horizontally behind a load balancer. We extract a service when a module needs independent deploys because of team size, a different runtime, or a compliance boundary; not for fashion, because each extraction adds network failure and data consistency work." Interviewers increasingly reward this answer over a reflexive microservices diagram.

Check yourself

A five-person startup proposes launching with twelve microservices 'so it scales later'. What is the strongest counter-argument?

Monoliths · Backplane