Monolithic architecture

Also known as: monolith

On this page 7

Monolithic architecture is a style of software architecture in which an application is built, tested and deployed as a single unit: the user interface logic, business logic and data access code live in one codebase, run in one process and usually share one database. Such an application is commonly called a monolith.

The monolith is the historical default for business software and remains a sound choice for many systems. Its simplicity of development and operations is the main strength, while limited independent scaling and deployment are the main costs as the codebase and the team grow.

How a monolithic application is structured

A monolith is defined by its deployment unit, not by the quality of its code. Internally it can be cleanly layered, for example presentation, business and persistence layers, yet all layers are compiled or packaged together and shipped as one artifact, such as a JAR or WAR file, a single binary or one container image.

Components communicate through in-process function calls, which take nanoseconds to microseconds, instead of network requests that take milliseconds. Transactions can span several modules through local ACID transactions in the shared database, so consistency is straightforward. Scaling is done by running identical copies behind a load balancer, each containing the whole application.

PropertyTypical form in a monolithEffect
CodebaseOne repository and buildEasy refactoring across modules
DeploymentOne artifact released at onceAny change redeploys everything
RuntimeOne process per instanceFast calls, shared memory, shared failure
Data storeOne shared database schemaSimple joins and transactions, tight coupling
ScalingHorizontal cloning of the whole appCannot scale one hot feature alone
Core characteristics of a monolith

Horizontal cloning works well only when instances are stateless: user sessions, uploaded files and caches must live in shared stores such as the database, a distributed cache or object storage. A monolith that keeps sessions in local memory needs sticky sessions at the load balancer, which weakens failover. Background jobs, scheduled tasks and the web front end can also run from the same artifact with different startup roles, which keeps one build while separating workloads at runtime.

Variants of the monolith

Not every monolith is the same, and the internal structure decides how long it stays maintainable. Practitioners distinguish several forms that differ in module boundaries and coupling.

VariantDescriptionMaintainability
Layered monolithHorizontal layers such as UI, service and dataGood while the domain is small
Modular monolithVertical modules with enforced boundariesHigh, and easy to split later
Big ball of mudNo clear boundaries, everything calls everythingPoor, changes are risky
Distributed monolithSeparate services that must deploy togetherWorst of both styles
Common forms of monolithic systems

The distributed monolith deserves special attention: it is a system split into network services that still share a database or require coordinated releases. It inherits the network costs of microservices without their independence, which is why a split must follow real domain boundaries.

The modular monolith is the variant most often recommended today. Each module owns its data tables, exposes a narrow public interface and is forbidden by architecture tests or build rules from reaching into the internals of other modules. Because the boundaries already exist, extracting a module into a service later becomes a mechanical change rather than a redesign.

Monolithic architecture compared with alternatives

Monolithic architecture is usually compared with microservices and service-oriented architecture, which split functionality into separately deployable services. The trade-off is between operational simplicity and independent change and scaling.

CriterionMonolithMicroservices
DeploymentOne pipeline, one releaseMany pipelines, independent releases
CommunicationIn-process callsHTTP, gRPC or messaging over a network
Data consistencyLocal transactionsEventual consistency, sagas
ScalingWhole applicationPer service
OperationsFew moving partsService discovery, tracing, many deployments
Team fitOne or a few teamsMany autonomous teams
Monolith versus distributed styles

A monolith is still compatible with client-server or three-tier architecture: the browser is the client, the monolith is the application tier and the database is the data tier. The term describes how the server-side application is packaged, not the overall topology.

When a monolith is the right choice

A monolith is the right choice when one team owns the product and the domain is still being discovered. Many experienced architects recommend a monolith first approach: start with a well-modularized monolith, learn where the real boundaries are and extract services only when a concrete need appears.

SituationRecommended choiceReason
New product, small teamMonolithFastest delivery, lowest operating cost
Growing team, unclear boundariesModular monolithKeeps options open
One component with extreme loadExtract that componentScale only the hot path
Many teams blocked by shared releasesMicroservicesIndependent deployment
Strict consistency across modulesMonolithLocal transactions stay simple
Decision guide for choosing the architecture

Limitations and warning signs

The weaknesses of a monolith grow with codebase size and team count. Build and test times stretch from minutes to an hour, merge conflicts multiply and a single memory leak or crash takes down every feature at once because all modules share the process.

  • Technology lock-in: the whole application must use one language and runtime version, so upgrades are large projects.
  • Coupled releases: a small fix waits for the next release train of unrelated features.
  • Inefficient scaling: a CPU-heavy report module forces cloning memory-heavy session handling too.
  • Eroding boundaries: without enforced module rules, the code drifts toward a big ball of mud.

These are signals to improve modularity first, not automatic reasons to rewrite. Enforcing module boundaries with build tools, separating database schemas per module and adding tests often removes most of the pain at a fraction of the cost of a migration.

In plain words

A monolithic application is like a single large shop that sells everything under one roof. Customers find everything in one place, the staff can walk between departments, and there is only one building to run.

The downside appears when the shop grows. Renovating one department means closing the whole store for a day, and a fire in the stockroom affects everyone. A monolith is simple to build and run, but it becomes harder to change piece by piece as it gets bigger.

A real-world example

A regional online retailer starts with a team of six developers and builds its shop as one web application: catalog, cart, checkout, customer accounts and admin tools in one codebase, deployed as one container image to two servers behind a load balancer, with one relational database.

For four years this setup lets the team release several times a week with a single deployment pipeline. When the team grows to 40 developers, releases slow down and the product search module consumes most of the CPU during sales events.

Instead of a full rewrite, the team enforces module boundaries inside the monolith and extracts only the search function into a separate service with its own index. The result is faster releases and cheaper scaling, while checkout and payments keep the simple local transactions of the monolith.