Microservices
Concept
An architecture that splits a product into several small services, each deployed on its own and calling the others over the network.
Why it exists
When all the code sat in one bundle, fixing a typo in a notification meant shipping the entire product again. Payments, document storage and notifications all lived inside the same program, so there was exactly one thing to put on a server. That shape is called a monolith.
Release evenings followed a script because of it. The person who fixed the typo waited for whoever was still finishing the payment work, everything went out together at eleven, and when something broke nobody could tell which change had caused it until three in the morning. The bigger the product got, the more people had to be in the room for a single release, and release cycles slid from weekly to monthly.
Microservices exist to break that bundle apart. Give each capability its own program, let each one ship separately, and the person who fixed the notification ships the notification while everyone else keeps their own schedule. The change is not about writing less code. It is about reducing how many people and how much risk one deployment drags along with it.
How it works
The product is cut into pieces by capability, and the pieces talk to each other only through an application programming interface (API). An API is an agreed-upon doorway that fixes what goes in and what comes back. Where a single program would have called a function directly, here the shape becomes "the order service sends a request to the payment service and waits for an answer."
For a piece to count as a service, four things have to belong to it alone.
- A boundary. One service owns one job. The payment service knows about payments and knows nothing about how documents are stored.
- Its data. Each service keeps its own database. If the payment service reads the document tables directly, the split stops meaning anything, so it asks the document service instead and takes whatever comes back.
- Its releases. Each service picks its own moment to ship. The notification service can go out three times a day while the payment service keeps running last month's build.
- Its size. Server counts are set per service too. If document storage gets busy, that service runs on ten machines while payments stays on two.
In practice each service is packaged into a container and run from there. A container bundles the program together with everything it needs to run, so it behaves the same way on any machine. That unit is what makes per-service releases cheap enough to do daily.
The arithmetic gets away from people quickly. Twenty services running three copies each is sixty containers, and deciding which machine holds which copy, or where to restart one that died at 4 a.m., is not work a human can keep up with. An orchestration tool takes that judgment over: you write down the state you want and it keeps putting reality back to it.
Where it shows up
Teams reach for this structure when one of three conditions bites.
The first is release speed. When several teams each want to ship a different capability every day but there is only one bundle to ship, they spend their time queueing behind each other. Split into five services and five releases a day happen without anyone coordinating.
The second is horizontal scaling, which means handling more load by adding more machines rather than buying a bigger one. In a single bundle, load anywhere forces you to scale everything. When search traffic jumps to ten times normal, running search on ten machines and leaving payments on two costs noticeably less than running ten copies of the whole product.
The third is team shape. Conway's law observes that a system's structure ends up mirroring the communication structure of the organization that built it, and this architecture uses that observation deliberately. Give one team one service end to end and there is less that has to be negotiated across team lines before anything ships.
Where to cut is its own question, and domain-driven design is the usual answer — drawing boundaries around how the business talks about the work rather than around database tables. Cutting by table shape tends to produce services that cannot do anything useful without three round trips to each other.
At 45 people, few teams start here. Five services means five deployment pipelines and five sets of dashboards, so splitting before the headcount arrives buys the operating cost without the benefit.
How it sounds at work
"This one only needs the notification service, so we don't have to wait on the payments release."
Deployment bundles are separate, so this change isn't tied to another team's calendar.
"That's a boundary problem. You're shipping three services to change one feature."
The split happened, but the lines don't match the work, so the benefit is gone.
"At our size we don't need microservices — let's just separate the modules."
The cost of splitting is currently larger than what splitting would buy.
Pagedeck runs four services: document editing, search, notifications and payments. Theo owns search and ships it twice a day without touching payments or notifications. When search went down for thirty minutes last month, editing kept working, so most people experienced it as a broken search box rather than an outage.
Splitting also created work that didn't exist before. On a day when notifications lag, a document is saved but the alert about it arrives minutes later. Mia decides during planning how that gap should look to a user, because the alternative is each service deciding for itself.
What people get wrong
The most common mistake is reading microservices as the more advanced version of a monolith. Well-known companies run this way, so the assumption is easy to make. But this is a trade rather than a step forward. You gain independent releases and independent scaling, and in exchange every function call that used to be incapable of failing becomes a network call that can be slow or never answer at all. A three-person team with twelve services has twelve pipelines and twelve sets of alerts, and when something breaks, finding which service started it takes a day. Surviving that requires observability — the instrumentation that lets you see what is happening inside a running system from the outside — before the split, not after.
The other belief that fails is that splitting stops failures from spreading. Separate services look like separate fates, but five services pointing at one shared database make that database a single point of failure. Splitting the code does not split the risk by itself, so the places that everything still depends on have to be hunted down again after the boundaries move.
Easily confused with
| Term | Deployment bundles | How it differs |
|---|---|---|
| Modular monolith | One | Modules are separated inside, but the whole thing ships as one unit. You get enforced boundaries without the operating cost, and you give up releasing or scaling one module on its own |
Where to go next
- Software architecture
see what teams weigh when choosing a structure at all
- Monolith
the structure before the split, which makes the trade clearer
- Conway's law
why service boundaries and team boundaries keep tracking each other
Last updated 2026-09-16