Monolith
A monolith is an application where all components (UI, business logic, data access) run in a single process and are deployed as one unit. Most successful applications start as well-structured monoliths.
Explanation
All features — authentication, users, products, orders, payments — live in one codebase and deploy together. Function calls between components are in-process (nanoseconds), not network calls (milliseconds). One codebase to search, one deployment pipeline, one set of logs, one database. Monoliths are often depicted negatively, but unfairly. A well-structured monolith is simpler to develop, test, and operate than microservices. Type systems validate cross-module calls at compile time. Transactions spanning multiple domains are trivial. Debugging is straightforward — everything is in one process. The problem people actually fear is the "big ball of mud" — a monolith with no module boundaries where every change risks breaking something unrelated. This is a design failure, not an inherent property of monoliths. A modular monolith enforces clear domain boundaries (like microservices) while keeping the simplicity of a single deployment. Shopify, Stack Overflow, Basecamp, and GitHub all ran significant monoliths at scale before selectively extracting services. The advice "don't start with microservices" is near-universal among senior engineers who have operated both.
Code Example
javascript// Modular monolith: domain boundaries in directory structure
// src/
// modules/
// users/
// users.routes.js — HTTP handlers
// users.service.js — business logic (the boundary)
// users.repo.js — database queries
// orders/
// orders.routes.js
// orders.service.js
// orders.repo.js
// app.js — wires modules together
// Cross-module: call via service interface only
const { getUser } = require('../users/users.service');
async function createOrder(userId, items) {
const user = await getUser(userId); // service interface
// NOT: const user = await db.query('SELECT * FROM users...') // bypasses boundary
}
// When to extract to a microservice:
// 1. A team needs to deploy independently without coordinating
// 2. One component needs dramatically different scaling (100x more requests)
// 3. You need a different technology stack for that domain
// 4. Domain boundaries are stable and well-understood
// NOT because microservices sound modern.
Why It Matters for Engineers
The monolith vs. microservices debate is a system design interview staple and a real architectural decision. Reflexively choosing microservices creates unnecessary complexity for teams that don't need it. Knowing when a structured monolith is correct — and being able to articulate why — demonstrates architectural judgment over fashion. Understanding monolith strengths also prepares you to recognize when microservice extraction is actually warranted: team autonomy blocked by coordination overhead, dramatically different scaling requirements, or genuine domain stability.
Related Terms
Learn This In Practice
Go deeper with the full module on Beyond Vibe Code.
Systems Design Fundamentals → →