Monolithic vs distributed
Before choosing a particular architecture style, there's a bigger fork in the road: one deployable unit, or many that talk over a network. Distributed architectures can scale parts separately, survive partial failures and let teams release independently. They also turn every function call into a network call, and the network breaks every assumption developers make inside one process. This module covers what you sign up for when you distribute.
1. The idea
| Monolithic styles | Distributed styles |
|---|---|
| One deployment unit, usually one database | Several deployment units talking over a network |
| Layered (Module 11), modular monolith (11), microkernel (12), pipeline | Service-based (13), event-driven (14), space-based (15), service-oriented (13), microservices (16) |
| Simple, cheap, fast in-process calls, easy transactions | Scale, fault tolerance and deployability per part |
| Scales, fails and releases as one unit | Pays for the network: latency, partial failure, consistency, operations |
The fallacies of distributed computing
Eight assumptions that are true inside one process and false across a network. Each one has caused real outages:
| The false assumption | What actually happens |
|---|---|
| 1. The network is reliable | Requests and replies get lost; you can't tell which |
| 2. Latency is zero | Each call costs milliseconds, not nanoseconds, and chains add up |
| 3. Bandwidth is infinite | Large payloads at high rates saturate links |
| 4. The network is secure | Traffic can be read or forged unless encrypted and authenticated |
| 5. Topology doesn't change | Instances come and go; addresses change constantly |
| 6. There is one administrator | Different teams and providers run different parts, with different rules |
| 7. Transport cost is zero | Serialisation, encryption and data transfer cost CPU and money |
| 8. The network is homogeneous | Different hardware, protocols and versions behave differently |
Three more are worth adding for architects: versioning is easy (it isn't: every contract change needs a plan, Module 25), compensating updates always work (an undo can fail too, Module 24), and observability is optional (without it, a distributed system can't be debugged at all).
2. How it works
Six fallacies, one call
The order service calls the inventory service. Each step breaks one in-process assumption and shows the usual fix.
Finding one failed request
In a monolith, one log file tells the story. Across services, the story is scattered. Watch the same failure investigated without and with a correlation ID.
3. Try it yourself
The cost of a call chain
A request that passes through several services synchronously succeeds only if every one of them is up, and waits for every one of them. Set the chain and see what users get.
Assumes services fail independently. Retries are modelled as fixing brief blips (about 70% of failures) but not real outages; in practice failures are often correlated, so treat the numbers as an optimistic bound. "Made asynchronous" moves the last two hops (notifications, analytics) off the request path.
4. Trade-offs
Simplicity vs independence
A monolith is easy to build, test, debug and deploy. Distribution buys independent scaling, deployment and fault isolation, at the price of every fallacy above.
Transactions vs availability
One database gives atomic transactions for free. Spread data across services and you trade them for eventual consistency and sagas (Module 24).
In-process speed vs network cost
A function call takes nanoseconds; a network call takes milliseconds and can fail. Chatty designs that were fine in a monolith become slow and fragile when split.
One thing to run vs many
Every extra service needs a pipeline, monitoring, alerts, on-call and upgrades. That operational cost is real, and it's often the deciding factor for small teams.
5. In real projects
Start monolithic unless you have a reason not to. The common advice for new products is to build a well-modularised monolith first, because the domain isn't understood yet and boundaries are cheap to move inside one codebase. Distribute when different parts need different characteristics, or teams need to release independently.
Every style has its own risks. Monoliths risk becoming a big ball of mud and having one bad release take everything down. Distributed styles risk the fallacies, data consistency problems, and the distributed monolith (Module 09). Name the risks of your chosen style in the decision record.
Budget for observability from day one. Correlation IDs, centralised logs, metrics per service and distributed tracing (OpenTelemetry is the common standard) aren't extras in a distributed system: without them, incidents take hours instead of minutes.
Say it in the interview
- "Monolith or microservices?" A modular monolith by default: simpler, cheaper and transactional. I'd distribute the parts that need different characteristics or independent releases, knowing that brings network failures, consistency and operational cost.
- "Name some fallacies of distributed computing." The network is reliable, latency is zero, bandwidth is infinite, the network is secure, topology doesn't change. Each one needs a design answer: retries with idempotency, fewer round trips, smaller payloads, mTLS, service discovery.
- "How do you debug a failure across services?" A correlation ID assigned at the edge and passed on every call, centralised logs, and distributed tracing. Then one ID shows the whole path of the failed request.
- Splitting into services "for scalability" with no characteristic that needs it.
- Long synchronous call chains with no timeouts or retries mentioned.
- No plan for logging and tracing across services.
6. Remember it
How this hook works: what "every arrow is a phone call" means
What the slogan means, phrase by phrase
- "Every arrow"
- Every interaction between deployment units on the diagram.
- "is a phone call"
- It takes time, may not connect, may be overheard, and the person may have moved. The fallacies, in one picture.
Why this picture fits: nobody assumes a phone call between branches is instant and certain; the hook makes you design each arrow with the same scepticism.
The story → the concept
| Branches and phone calls | Distributed system |
|---|---|
| The line drops | The network isn't reliable |
| Each call takes minutes | Latency isn't zero |
| A colleague moved desk | Topology changes |
| A reference number on every case | A correlation ID |
The trap it saves you from
Drawing a distributed system with the same carelessness as a class diagram.
7. Common mistakes
8. Design exercise (30 minutes)
- Walk the fallacies (15 min). Take one network call in a system you know. For each of the eight fallacies, write what happens if it's violated and what protects against it today.
- Price the chain (10 min). Find your longest synchronous call chain. Use the lab to estimate its availability and latency.
- Trace one request (5 min). Could you find every log line for one failed request across services today? If not, write what's missing.
9. Self-check quiz
Five services, each 99.9% available, called synchronously in a chain. What's the chain's availability?
A reply is lost and the caller retries. What prevents a double reservation?
What lets you find every log line for one failed request across services?
Calls fail after the autoscaler replaces an instance with a new address. Which fallacy?
When is it worth moving from a monolith to a distributed style?
10. Go deeper
| Resource | Time | Why |
|---|---|---|
| Fallacies of distributed computing | 10 min | The eight fallacies and their history. |
| MonolithFirst (Martin Fowler) | 10 min | Why most successful distributed systems started as monoliths. |
| Traces (OpenTelemetry) | 20 min | How distributed tracing ties one request together across services. |