Contact

What is Monolithic Architecture?

Definition

Monolithic architecture is a software design in which all of an application's functionality lives in one codebase and is built and deployed as a single unit. Modules such as catalogue, orders and billing run in the same process, call each other directly and usually share one database. When the internal module boundaries are strictly enforced, the result is called a modular monolith.

Also known as: monolith, monolithic application, modular monolith, majestic monolith

Monolithic app with all modules, one codebase and a shared database deployed together, compared with the same app split into services

One deployable unit

What makes a system a monolith is not its size but the fact that it ships as one unit. In an online store, catalogue, basket, orders and invoicing live in the same project, compile into one artefact and go to production together. Modules talk through in-process function calls rather than over the network.

A common myth is that monoliths cannot scale. The same build can run on dozens of servers side by side behind a load balancer. The real ceiling is usually the shared database, and that problem exists whatever the architecture.

Strengths that get overlooked

  • Simple releases — one pipeline, one version number, one rollback.
  • Consistency is cheap — saving an order and decrementing stock can happen in one database transaction: both succeed or neither does.
  • Debugging — a single log stream and a single stack trace show what happened to a request.
  • Refactoring is affordable — change a function signature and the compiler or test suite points at every caller at once.
  • Speed — an in-process call is orders of magnitude faster than a network round trip, and it cannot time out halfway.

What actually goes wrong

When monoliths earn a bad reputation, the culprit is usually unchecked coupling rather than the single deployment. If every module queries every other module's tables and a few "helper" classes know about everything, small changes break distant features. This is the infamous "big ball of mud", and it is one of the most expensive forms of technical debt. Practical pains pile up on top: build and test times grow, a memory leak in one module takes the whole application down, and the most resource-hungry module forces everything onto bigger machines.

Building a modular monolith

A modular monolith keeps the single deployment but draws internal boundaries as strict as service boundaries would be. A typical layout:

src/
  modules/
    catalog/
      index.ts        // the module's only public entry point
      internal/       // off-limits to other modules
    orders/
      index.ts
      internal/
    billing/
      index.ts
      internal/
  shared/             // genuinely generic utilities only

A few rules make the structure hold:

  • Each module owns its tables. Orders never writes SQL against catalogue tables; it asks the catalogue module's public functions. Separate database schemas per module make the ownership visible.
  • Boundaries are enforced by tooling. Lint rules or the language's package visibility should fail the build when someone imports from another module's internal folder. Rules that only live in a wiki erode within months.
  • Side effects travel as events. Orders publishes an in-process "order placed" event and billing subscribes to it, so orders does not need to know billing exists.

Done this way, you get most of the organisational clarity people seek in services while keeping in-process calls and real transactions.

Extracting a service later

When one module genuinely needs to scale on its own or be released by a separate team on its own schedule, a well-bounded module can become a microservice. The usual route is the strangler fig pattern: stand up the new service alongside the monolith, shift traffic to it step by step, and delete the old code only once nothing calls it. With clean module boundaries, that is weeks of work. Without them, the first job is tidying up the inside of the monolith.

Related terms

← Back to the glossary