What Makes a System Distributed

LESSON

Distributed Systems Foundations

002 25 min beginner

What Makes a System Distributed

By the end of this lesson, you will be able to...

  • identify participants, messages, owners, and promises in a small system.

  • explain why distribution starts before microservices or multiple regions.

  • classify whether a user action needs distributed-systems reasoning.

Idea in one sentence: A system becomes distributed when one useful promise depends on independent participants learning about each other through messages.

Core Insight

Imagine a notes app.

You type a grocery list on your laptop. A few seconds later, you expect the same list to appear on your phone. The product promise sounds simple:

When I save a note on one device,
my other devices should eventually show the same note.

At first, it feels like one app with one note. But the system is already split across independent participants. The laptop has a local copy. The phone has another local copy. A sync service stores the server copy. A database stores durable state. A background worker may send changes to other devices.

Now make one ordinary thing happen: the laptop goes offline after saving the note.

The laptop can see the newest text. The server cannot. The phone still shows the old text. No component is confused from its own point of view. The user promise is what became hard.

That is the moment distributed-systems reasoning begins.

The question is not "How many services are in the architecture diagram?" The question is:

Does a useful promise depend on independent participants exchanging messages?

If yes, the system is meaningfully distributed for that promise.

Plain meaning:

Parts of the system can move separately. They do not share one instant truth.

In this scenario:

The laptop can save a note while the phone and server do not know about it yet.

Technical name:

Those parts are independent participants. The note update must cross message boundaries before the whole system can act as if it agrees.

The Naive Idea

The tempting model is simple:

There is one note.
Saving changes the note.
Reading shows the note.

That model works when everything is local. One process, one memory space, one file, one immediate answer.

For a local-only notes app, the path can be tiny:

editor -> local file: write note
editor <- local file: write finished

The editor can often treat the write as a direct action. It is still possible for local storage to fail, but the system has one small failure boundary.

The naive idea breaks as soon as the product promise crosses devices:

laptop saves: "milk, eggs, tea"
network is offline
server still has: "milk, eggs"
phone reads from server
phone shows: "milk, eggs"

Which value is "the note"?

That question does not have one answer unless the system defines ownership, messages, timing, and repair. The laptop owns a local edit. The server owns the shared copy it has accepted. The phone owns what it has last received. The product promise has to survive the gap between those facts.

Check: Is the notes app distributed only after it has many backend services?

Think first, then reveal.

Answer: No. The laptop, phone, sync service, and database are already independent participants. The promise crosses message boundaries even if the backend is one simple service.

The Four-Part Test

Use this test when you are unsure whether a workflow needs distributed thinking.

Ask four questions:

1. Who are the independent participants?
2. What messages cross between them?
3. Who owns the official fact at each moment?
4. What promise depends on those messages?

For the notes app:

participants:
  laptop app
  phone app
  sync API
  notes database

messages:
  upload edit
  acknowledge edit
  fetch latest note
  push or poll update

owners:
  laptop owns the local unsynced edit
  database owns the accepted server copy
  phone owns its displayed cached copy

promise:
  a saved note should not silently disappear,
  and other devices should converge to the accepted update

This test is more useful than counting machines. One service plus one database can be distributed for a write promise because the service and database can fail or commit independently. A phone plus a server can be distributed because the phone can work offline. A file written by one batch job and read by another can be distributed if the downstream promise depends on that handoff.

A huge codebase inside one process may be complicated, but not distributed in this sense. Complexity is not the same as distribution. Distribution appears when a promise must cross an independent boundary.

A Worked Classification

Classify four versions of the notes app.

Design Shape Distributed for the sync promise? Why
A One local editor writes one local file. No, not for sync. There is no cross-participant sync promise.
B Browser sends notes to one server and one database. Yes. Browser, server, and database can each know different facts.
C Laptop works offline, then syncs to server and phone. Yes. Local edits and server state can diverge.
D Two regions accept edits and replicate later. Yes, with stronger conflict pressure. Both regions may accept different edits before they communicate.

Design A can still have bugs. It can corrupt a file or lose data if the disk fails. But the specific problem of distributed agreement across participants is mostly absent.

Design B is already distributed. Suppose the server writes the note to the database, but the response to the browser is lost. The browser may show "save failed" while the database holds the new note. The database owns the durable fact. The browser owns the waiting experience.

Design C adds offline work. The laptop can create a new fact while disconnected. The server cannot accept that fact until a message arrives. The phone cannot display it until it learns about it. The system needs a rule for "saved locally but not yet synced."

Design D adds concurrent owners. If two regions accept different edits to the same note during a network partition, the system needs a conflict rule. Last write wins, merge, manual conflict, and per-field merge are different product choices.

So far, we have a useful classification: a system is distributed for a promise when the promise crosses participants that can act, wait, fail, or store state independently.

Evidence Moves Across Boundaries

The central mental model is this:

Truth does not move directly.
Evidence moves in messages.

When the laptop saves a note, it does not place truth inside the phone. It stores local state and later sends evidence:

message:
  note_id: note-7
  edit_id: edit-91
  text: "milk, eggs, tea"
  base_version: 12

The server reads that message and decides what to do. It might accept the edit as version 13. It might reject it because the server already has version 14. It might store it but fail before sending the acknowledgment. It might send an acknowledgment that arrives late.

Here is a small trace:

Step Participant Local fact Message or decision
1 Laptop User edited note-7. Stores edit-91 locally.
2 Laptop Network is back. Sends edit-91 to sync API.
3 Sync API Receives edit-91. Writes version 13 to database.
4 Database Version 13 exists. Returns commit success.
5 Sync API Commit succeeded. Sends acknowledgment.
6 Network Acknowledgment is delayed. Laptop still shows "syncing."

The naive failure contrast matters. If the laptop treats the missing acknowledgment as "the server rejected my edit," it may warn the user incorrectly or create a second unrelated edit. If it treats the edit as definitely synced, it may hide a real problem. The honest state is:

local edit exists
server outcome not yet confirmed by this participant

That state is less tidy than saved or failed, but it matches the evidence.

What This Is Not

Distributed does not mean "uses microservices." Microservices are one way to build distributed systems, but a mobile app syncing with one server already has the core problem.

Distributed does not mean "large." Small systems can have distributed failure modes. A browser, one API server, and one database are enough to create uncertainty after a timeout or lost response.

Distributed does not mean "bad." Distribution can buy useful things: offline work, shared state across devices, higher availability, lower latency near users, independent team ownership, or more capacity. The cost is that the system needs explicit rules for messages, ownership, ordering, and repair.

Distributed also does not mean "every component gets to decide the truth." Participants can have local facts. The system still needs owners. If the database owns accepted note versions, then the phone should not invent the accepted server version from a stale cache. If the laptop owns unsynced local edits, the server should not pretend those edits do not exist once they arrive.

Trade-offs and Limits

The trade-off is that distribution buys useful product behavior by making evidence harder to collect.

The four-part test improves design conversations. It forces the team to name the participants, messages, owners, and promise before choosing mechanisms.

It costs a little patience. It is slower than saying "just call the API" or "just sync it." That cost is worth paying when the workflow can produce conflicting local facts.

The test does not solve consistency, retries, conflict resolution, or latency by itself. It only tells you where those problems can appear.

You can see the boundary when a missing, delayed, duplicated, or reordered message would change what the user sees or what the system is allowed to promise.

Common Confusions

Confusion: A system is distributed only when it has many servers

Why it is tempting:

Architecture diagrams often make distribution look like a big-system problem.

Better model:

Distribution starts when a promise crosses independent participants. One app, one server, and one database can be enough.

Confusion: If the UI is simple, the system is simple

Why it is tempting:

The user sees one button: Save.

Better model:

The button may trigger local storage, upload, database write, acknowledgment, and sync to other devices. The UI hides the boundary; it does not remove it.

Confusion: Messages carry truth

Why it is tempting:

A message often sounds authoritative: "version 13 saved."

Better model:

A message is evidence. The receiver still needs to know who sent it, what state it refers to, whether it is stale, and which owner can confirm it.

Practice

Pick one action from an app you use: saving a note, liking a post, joining a call, uploading a receipt, or marking a task done.

Write this table:

action:
participants:
messages:
official owner of the main fact:
local fact each participant can know:
promise that crosses the boundary:
what could become unknown:

Then classify the action:

local only
small distributed system
multi-participant distributed workflow

A good answer should name at least two independent participants, one message, one owner, and one promise. If your answer only says "the app saves data," split it into who saves what, who learns about it later, and what the user expects to remain true.

Resources

Key Takeaways

PREVIOUS The Distributed Systems Mindset NEXT Network Boundaries, Latency, and Partial Failure