InterviewKata
Software architecture · Level 3: Architecture styles · Module 10 of 46

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.

See it builtThe Architecture styles track builds these styles for one bike-share app, with code you can run: 01 Monolith and modular monolith · 06 Client-server and tiers.

1. The idea

One office or several branches. In one office, you lean over and ask a colleague; the answer is instant, and if the building has a power cut, everyone stops together. With branches in five cities, each can open longer hours, grow on its own and keep working if another closes. But every question becomes a phone call that might not connect, might be slow, or might reach the wrong person after someone moves desk, and you need a way to find out which branch lost a customer's order.
Monolithic stylesDistributed styles
One deployment unit, usually one databaseSeveral deployment units talking over a network
Layered (Module 11), modular monolith (11), microkernel (12), pipelineService-based (13), event-driven (14), space-based (15), service-oriented (13), microservices (16)
Simple, cheap, fast in-process calls, easy transactionsScale, fault tolerance and deployability per part
Scales, fails and releases as one unitPays 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 assumptionWhat actually happens
1. The network is reliableRequests and replies get lost; you can't tell which
2. Latency is zeroEach call costs milliseconds, not nanoseconds, and chains add up
3. Bandwidth is infiniteLarge payloads at high rates saturate links
4. The network is secureTraffic can be read or forged unless encrypted and authenticated
5. Topology doesn't changeInstances come and go; addresses change constantly
6. There is one administratorDifferent teams and providers run different parts, with different rules
7. Transport cost is zeroSerialisation, encryption and data transfer cost CPU and money
8. The network is homogeneousDifferent 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.

5

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

Two-sentence answers
  • "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.
Red flags interviewers notice
  • 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

Memory hook: "Every arrow is a phone call"In a distributed design, each arrow can be slow, fail, be overheard or reach the wrong place. Price every one.
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 callsDistributed system
The line dropsThe network isn't reliable
Each call takes minutesLatency isn't zero
A colleague moved deskTopology changes
A reference number on every caseA correlation ID

The trap it saves you from

Drawing a distributed system with the same carelessness as a class diagram.

7. Common mistakes

Retries without idempotencyA retried "reserve 2" after a lost reply reserves 4. Every retried operation needs an idempotency key.
Chatty calls across the networkTen small calls that took microseconds in-process now take hundreds of milliseconds. Batch, cache, or redraw the boundary.
Hard-coded addressesInstances move. Use service discovery or a load balancer name, never an IP in config.
Observability as an afterthoughtAdding correlation IDs after the first major incident is too late for that incident.

8. Design exercise (30 minutes)

  1. 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.
  2. Price the chain (10 min). Find your longest synchronous call chain. Use the lab to estimate its availability and latency.
  3. 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?

0.999⁵ ≈ 0.995: about 3.6 hours of failures a month instead of 43 minutes.

A reply is lost and the caller retries. What prevents a double reservation?

The callee recognises the repeated request and returns the original result.

What lets you find every log line for one failed request across services?

One ID, assigned at the edge, ties the scattered lines together.

Calls fail after the autoscaler replaces an instance with a new address. Which fallacy?

Use service discovery so callers always find current instances.

When is it worth moving from a monolith to a distributed style?

Distribution's costs are only worth paying for a benefit you actually need.

10. Go deeper

ResourceTimeWhy
Fallacies of distributed computing10 minThe eight fallacies and their history.
MonolithFirst (Martin Fowler)10 minWhy most successful distributed systems started as monoliths.
Traces (OpenTelemetry)20 minHow distributed tracing ties one request together across services.