Module 05 // Async and communicationLesson 19 / 3418 min read
Microservices vs monolith
A monolith is one app deployed as a unit; microservices split the app into small services that each own one business area and deploy independently. Microservices help large teams move fast, but add a lot of distributed complexity.
Think of it like this
Analogy
A monolith is a single big restaurant kitchen. Everyone works in one room with one set of recipes. Communication is easy (you just shout), but when there are 200 cooks it gets crowded, and changing one station's layout disturbs everybody.
Microservices are a food hall: separate stalls for pizza, sushi and dessert, each with its own staff, kitchen and menu. Each stall can change its recipes on its own schedule. But now you need signs to find stalls, a shared payment system, and someone to coordinate when an order needs food from three of them.
The problem it solves
As a product and its team grow, a single codebase can become a bottleneck. Every deploy ships everything, so one team's bug blocks another team's release. Test suites take an hour. Everyone needs to understand everything. One memory leak in a rarely used feature takes down the whole app. And you can't scale the busy part (search) without scaling the rest.
But splitting too early creates a different set of problems, often worse ones.
A real example
Example
A marketplace outgrows its monolith
An online marketplace started as one app with one database, and for three years that was the right call. Now 60 engineers work in the same codebase. A deploy needs sign-off from five teams, and a bug in the reviews page once took down checkout.
They split out two services first. Payments has strict security rules and its own team. Search needs very different hardware. Each gets its own database and talks to the rest through APIs, with an API gateway in front.
Deploys get faster for those teams. They also gain new problems: network calls that time out, data spread over several databases, and the need for tracing to see why a request was slow.
How it works
Monolith
A monolith is one deployable application with one database. A modular monolith organizes the code into well-separated modules (orders, users, payments) that talk through clear internal interfaces. It keeps most of the benefits of separation with none of the network problems, and it's the recommended starting point for most teams.
Microservices
Microservices split the system along business areas. Each service:
- owns one area (orders, payments, catalog) and its own data;
- deploys independently, on its own schedule;
- talks to others over APIs (REST, gRPC) or events (lessons 17–18).
- Clients to API gateway
- API gateway to Users service
- API gateway to Orders service
- API gateway to Payments service
- Users service to Users DB
- Orders service to Orders DB
- Orders service to Event bus: OrderPlaced
- Payments service to Event bus
The supporting pieces
- API gateway: one entry point for clients. It routes
/orders/*to the orders service, checks auth tokens, applies rate limits and logs requests. - Service discovery: services come and go as they scale, so callers look them up by name in a registry, or use the platform's DNS (as in Kubernetes).
- Service mesh (optional): a proxy next to each service that handles retries, timeouts, encryption between services and metrics, without changing app code.
- Observability: with requests crossing many services, distributed tracing (lesson 24) becomes essential.
What gets harder
| Concern | Monolith | Microservices |
|---|---|---|
| A call between features | In-memory function call | Network call that can fail or be slow |
| Transactions across areas | One database transaction | Sagas and eventual consistency |
| Debugging a request | One log file | Traces across many services |
| Local development | Run one app | Run or mock many services |
| Deploy | One pipeline | Many pipelines; version compatibility |
Splitting well
- Split along business capabilities, not technical layers (not a “database service”).
- Each service should be deployable alone. If two services must always deploy together, they're really one.
- Avoid chatty chains: if one page needs ten synchronous calls in a row, latency and failure risk add up.
- Use the strangler fig pattern to migrate: route one feature at a time from the monolith to a new service until the monolith is gone.
Trade-offs
What you gain
- Teams own, deploy and scale their services independently.
- A failure in one service can be contained.
- Each service can use the best tools for its job, and the hot parts scale on their own.
What it costs you
- Network calls add latency and new failure modes.
- Data is spread out: cross-service queries and transactions are hard.
- Much more infrastructure: gateways, discovery, tracing, many pipelines.
- Easy to end up with a “distributed monolith”: tightly coupled services that are worse than one app.
When not to use it
- Small teams and young products, where the domain boundaries aren't clear yet. Start with a modular monolith.
- When the main problem is performance; splitting rarely makes things faster by itself.
In the cloud
Containers and KubernetesEvery major cloud sells this as a managed service, so you configure it rather than build it.
AWS2
- Amazon ECS (opens vendor docs)
AWS's own container orchestrator; runs on EC2 or serverless with Fargate.
- Amazon EKS (opens vendor docs)
Managed Kubernetes.
Azure2
- Azure Kubernetes Service (AKS) (opens vendor docs)
Managed Kubernetes.
- Azure Container Apps (opens vendor docs)
Serverless containers for microservices, with built-in service discovery and scaling.
Google Cloud2
- Google Kubernetes Engine (GKE) (opens vendor docs)
Managed Kubernetes, including a hands-off Autopilot mode.
- Cloud Run (opens vendor docs)
Runs containers without managing clusters; scales with requests.
An API gateway routes each path to its own service; services find each other by name.
- Amazon API Gateway
- Application Load Balancer
- ECS services on Fargate
- Per-service databases
Service discoveryEvery major cloud sells this as a managed service, so you configure it rather than build it.
AWS2
- AWS Cloud Map (opens vendor docs)
A registry of your services and their addresses, queried by name over DNS or API.
- Amazon ECS Service Connect (opens vendor docs)
Lets ECS services call each other by name, with retries and metrics; the replacement for App Mesh on ECS.
Azure2
- AKS (Kubernetes services and DNS) (opens vendor docs)
Kubernetes gives every service a stable DNS name inside the cluster.
- Azure Container Apps (opens vendor docs)
Apps in the same environment reach each other by app name.
Google Cloud2
- Service Directory (opens vendor docs)
A managed registry for looking up services by name across environments.
- Cloud Service Mesh (opens vendor docs)
Managed service mesh for traffic management, security and telemetry between services.
Interview questions
Try answering out loud first, then open the model answer.
Monolith or microservices for a new startup? Why?
Model answer
A modular monolith. With a small team the biggest risks are speed and figuring out the product, and microservices add operational overhead, network failures and data consistency problems that slow you down. I'd keep strong module boundaries, with separate packages, no reaching into other modules' tables, and clear interfaces, so that if a part later needs to scale or be owned by a separate team, it can be extracted.
How do you handle a business transaction that spans several services, like placing an order?
Model answer
With a saga instead of a distributed transaction. For example: Orders creates the order as “pending” and emits OrderCreated; Inventory reserves stock and emits StockReserved (or StockFailed); Payments charges and emits PaymentCaptured (or PaymentFailed); Orders then marks the order confirmed, or triggers compensating steps such as releasing stock or refunding. Each step is idempotent and its event is published reliably with the outbox pattern. The user sees “processing” until the saga finishes.
What's a distributed monolith and how do you avoid it?
Model answer
It's a system split into services that still have to change, deploy and stay up together, through shared databases, synchronous call chains or shared libraries with business logic. You get the costs of microservices without the independence. Avoid it by drawing boundaries around business capabilities, giving each service its own data, preferring events over long synchronous chains, versioning APIs to stay backward compatible, and checking that each service can be deployed on its own.
Quiz
Pick an answer to see whether it’s right and why.
0 of 6 answered
Key terms
- Monolith
- One application that contains all features, deployed as a single unit.
- Microservices
- An app split into small services, each owning one business area and its own data, deployed independently.
- API gateway
- The single front door for clients that routes requests to services and handles auth, limits and logging.
- Service discovery
- How services find the current network addresses of other services by name.
- Service mesh
- A layer of proxies beside each service that handles retries, encryption and metrics for service-to-service traffic.
Progress is saved in this browser only.