# 11. Monolith and microservices

How to choose between a modular monolith and microservices, when a split is justified, what price distribution carries, and why a service isn't the same as a boundary.

- **Author:** Fedor Chishchin
- **Level:** advanced
- **Reading time:** ~25 minute read
- **Published:** 2026-05-23
- **Source:** https://fedorthinks.com/learn/software-architect-11-monolith-microservices

---

## 1. The core idea

Microservices buy independence at the price of distributed complexity. If you don't need the independence, the price is wasted.

### A service is an organizational unit

> A separate office helps when a team has its own work, rhythm, and responsibility. If everyone is on the same call anyway, the walls don't help.

A microservice is justified when the context has its own lifecycle, owning team, load profile, security requirements, or release rhythm. Pulling code into a separate deployable unit isn't enough.

A **modular monolith** is often better early on: one codebase and one deployment, but strict internal modules, public interfaces, no circular dependencies, and clear ownership.

### Distribution adds an operational price

> One kitchen can be cramped. Ten kitchens require logistics, communication, delivery schedules, and rules for handing dishes off.

Microservices require service discovery, observability, network security, backward-compatible contracts, distributed tracing, deployment orchestration, incident response, data ownership, and SRE practices. None of that is a downside if there's a reason for it. It's the price.

The architect has to ask honestly: which pain goes away after the split, and which new pain appears?

## 2. Example and anti-example

A good split reduces coordination. A bad split creates more sign-off meetings than there were before it.

### Example: extracting billing

> The register, the accounting office, and the warehouse are connected, but accounting has its own rules, audits, and responsibility.

Billing has its own compliance requirements, audit trail, integrations with payment providers, and an owning team. It can be extracted into a service with its own data and contracts: invoices, subscriptions, payment events.

That split makes sense: it protects a domain with a high cost of error and a separate pace of change.

### Anti-example: a microservice per table

> If every shelf of the warehouse became a separate shop, the customer would have to walk through ten checkouts for one order.

The team builds `users-service`, `profiles-service`, `addresses-service`, `roles-service`, but every use case requires calls to all four. The data is still coupled, releases are still coordinated, and latency and debugging are both worse.

That's a distributed monolith: there are services, but no independence.

#### Self-check

- Which team will own this service?
- Can the service be released independently?
- Whose data does it own?
- Which new operational responsibilities appear after the split?

Next module: [Sync and async](./software-architect-12-sync-async).
