Monolith vs. Microservices
Session 1.5 · ~5 min read
Two Ways to Build Software
Every application starts as a single thing. One codebase, one deployment, one process. At some point, teams face a decision: keep it together or break it apart. This is the monolith-versus-microservices question, and it is one of the most consequential architectural decisions you will make.
The answer is rarely obvious, and the industry has swung between extremes. Understanding the real tradeoffs, not the marketing, is what matters.
The Monolith
A monolithic architecture deploys the entire application as a single unit. All modules, whether they handle user authentication, payment processing, notifications, or reporting, live in one codebase and run in one process (or a set of identical processes behind a load balancer).
Monolith: A software architecture where all components are packaged and deployed as a single unit. Function calls between modules happen in-process, not over the network.
Monoliths are not inherently bad. They have real structural advantages:
- Simple deployment. One artifact to build, test, and ship. No coordination between services.
- Easy debugging. A stack trace shows you the full call path. No distributed tracing needed.
- In-process communication. A function call takes nanoseconds. A network call takes milliseconds. That is a six-order-of-magnitude difference.
- Single database. Transactions are straightforward. ACID guarantees come free.
- Lower operational overhead. One thing to monitor, one thing to scale, one thing to secure.
The problems emerge as the team and codebase grow. A change to the payment module requires redeploying the entire application. A memory leak in the reporting module crashes the authentication module. A team of 80 engineers stepping on each other in the same repository slows everyone down.
Microservices
A microservice architecture decomposes the application into small, independently deployable services. Each service owns a specific business capability, runs in its own process, and communicates with other services over the network (typically HTTP/REST or gRPC).
Microservices: An architectural style where the application is composed of loosely coupled, independently deployable services, each responsible for a specific business capability and maintaining its own data store.
The advantages are real but come with costs:
- Independent deployment. Ship the payment service without touching authentication. Faster release cycles per team.
- Team autonomy. Each team owns a service end-to-end. They choose their own language, framework, and release schedule.
- Fault isolation. If the reporting service crashes, the payment service keeps running.
- Targeted scaling. Scale the service that needs it, not the entire application.
The costs:
- Network complexity. Every function call that was in-process is now a network call. Latency, retries, timeouts, circuit breakers.
- Data consistency. No cross-service transactions. You need sagas, eventual consistency, or careful domain boundaries.
- Operational overhead. Dozens or hundreds of services to deploy, monitor, log, and trace. You need CI/CD pipelines, container orchestration, service meshes, distributed tracing.
- Integration testing. Testing the interaction between services is harder than testing a monolith's internal calls.
Comparison Across Dimensions
| Dimension | Monolith | Microservices |
|---|---|---|
| Deployment | Single artifact, all-or-nothing | Independent per service |
| Codebase | One repository (usually) | Many repositories or monorepo |
| Communication | In-process function calls | Network calls (HTTP, gRPC, messaging) |
| Data management | Single shared database | Database per service |
| Scaling | Scale entire application | Scale individual services |
| Debugging | Single stack trace, single log | Distributed tracing across services |
| Team structure | Teams share one codebase | Teams own individual services |
| Fault isolation | One failure can crash everything | Failures contained to one service |
| Time to first deploy | Fast (minimal infrastructure) | Slow (needs orchestration, CI/CD) |
Conway's Law
In 1967, Melvin Conway observed that "any organization that designs a system will produce a design whose structure is a copy of the organization's communication structure." This observation, later named Conway's Law, explains why architecture decisions and team decisions are inseparable.
Conway's Law: The architecture of a system mirrors the communication structure of the organization that builds it. A company with four teams will produce a system with four major components, regardless of what the optimal architecture might be.
Conway's Law works in both directions. If you have a single team, a monolith is natural and effective. As Martin Fowler notes, "a dozen or two people can have deep and informal communications, so Conway's Law indicates they will create a monolith, and that is fine." If you have 15 teams and force them into one monolith, they will create implicit service boundaries anyway through code ownership conventions, module walls, and meeting schedules.
The Inverse Conway Maneuver deliberately structures teams to encourage the desired architecture. Want microservices? Create small, autonomous teams organized around business capabilities. Want a well-structured monolith? Keep the team small and communicating tightly.
When to Start With What
Martin Fowler's "Monolith First" argument is straightforward: almost all successful microservice stories started with a monolith that grew too big and was broken up. Almost all cases where systems were built as microservices from scratch ended up in serious trouble.
The reasoning is practical. Early in a product's life, you do not know where the real boundaries are. You do not know which features will matter, which will be thrown away, and where the load will concentrate. A monolith lets you discover these boundaries cheaply. Refactoring a function boundary inside a monolith is an afternoon of work. Redrawing a service boundary in a microservice system means migrating data, rewriting APIs, and coordinating multiple teams.
The signal that you might need to break apart is usually organizational, not technical. When the team is large enough that people are blocked by each other. When deployment frequency drops because too many changes are coupled. When a single module's scaling needs are dramatically different from the rest. These are structural pressures that microservices address.
The Modular Monolith: A Middle Path
A modular monolith maintains strict module boundaries inside a single deployment. Modules communicate through defined internal APIs, not by reaching into each other's database tables or internal classes. The code is structured as if it could be split into services, but it runs as one process.
This approach captures the deployment simplicity of a monolith while maintaining the clear boundaries that make a future migration to microservices feasible. Shopify famously operates a modular monolith that serves millions of merchants, demonstrating that you do not need microservices to reach enormous scale.
Further Reading
- Martin Fowler, "Monolith First" (martinfowler.com). The argument for starting with a monolith and extracting services only when the need is proven.
- Martin Fowler, "Microservice Trade-Offs" (martinfowler.com). A balanced analysis of what you gain and what you pay when adopting microservices.
- Martin Fowler, "Conway's Law" (martinfowler.com). How organizational structure shapes system architecture, and vice versa.
- Sam Newman, Building Microservices, 2nd Edition (O'Reilly, 2021). The standard reference for microservice architecture, including decomposition strategies and data management patterns.
- Melvin Conway, "How Do Committees Invent?" (1968). The original paper that introduced Conway's Law.
Assignment
This assignment has two parts.
Part 1: Write a 3-sentence argument FOR starting with a monolith for a new startup building a food delivery app. Address why a monolith is the right choice at this stage.
Part 2: Write a 3-sentence argument for WHEN to break the monolith apart. Identify the specific signals (team size, deployment pain, scaling bottlenecks) that would trigger the transition to microservices.
In both parts, reference Conway's Law. How does the team's current structure support your recommendation?