Architecture patterns
Monoliths and microservices
When to split a system, how to draw service boundaries, and the operational cost that microservices add.
Few architecture decisions cause as much argument as "monolith or microservices?" In the 2010s, microservices became the default answer, and teams of eight split their apps into twenty services. By the 2020s the pendulum had swung back. Segment merged more than 140 services into one, and Shopify championed a modular monolith.
Both camps are right about different situations. The useful question is not which architecture is better. It is where the boundaries in your system should go, and how strong each boundary needs to be.
Splitting is mostly an organizational decision. It lets separate teams deploy on their own schedules. It also brings network calls, separate databases and a large operational load.
A sensible default is to start as a modular monolith with enforced module boundaries. Split a module out only when a specific pressure appears: a team that can't ship without waiting on others, a workload that needs different scaling, or a compliance boundary. Each split adds network calls, a database and a deploy pipeline, so every service should earn its place. Shopify's modular monolith is a working example of this approach. The pages below take those ideas in order, starting with the cheapest option that works.
Concepts in this section
| Step | Concept | What it answers |
|---|---|---|
| 1 | Monolith vs microservices | What are the options, and what does each cost? |
| 2 | Conway's law and team shape | Why does organization structure drive architecture? |
| 3 | Bounded contexts | Where should the boundaries go? |
| 4 | Service communication | Should services call each other, or send events? |
| 5 | Database per service | Who owns the data? |
| 6 | The operational tax | What must exist before you split? |
| 7 | Strangler fig migration | How do you move off a monolith without a rewrite? |
Common mistakes
- Splitting by technical layer. A "validation service" or "database service" means every feature touches every service.
- Building a distributed monolith. Services that must be deployed together, or share a database, carry all of the cost and none of the independence.
- Splitting before the boundaries are known. Boundaries become network APIs, which are hard to move. Start with a well-structured modular monolith.
- Splitting a small team. Twelve services for eight engineers adds operations and no organizational benefit.
Key takeaways
- Monolith, modular monolith and microservices are points on a spectrum of boundary strength.
- Microservices are mainly an organizational tool, which Conway's law explains.
- Draw boundaries around business capabilities, and expect few, coarse crossings.
- Each service owns its data, and synchronous chains multiply unavailability.
- Add services when a specific pressure justifies them, and migrate with the strangler fig.
Further learning
Martin Fowler's GOTO talk is a compact tour of what microservices are and when they are worth it.
Start with monolith vs microservices.
Related
Event-driven architecture, CQRS and event sourcing
Building systems around events, from change data capture to event sourcing and read models, and knowing when it simplifies a system versus creating a distributed mess.
API design
An API is a contract that outlives the code behind it. Design the styles, methods, pagination, errors and async flows so changes stay additive.
Platform engineering
Internal developer platforms, golden paths and treating infrastructure as a product. Cut cognitive load without building a second Kubernetes.