Why leave one machine at all?
Everything you have learned so far lived inside a single computer. One kernel managed one set of physical memory, one disk, one collection of processes, all watched over by one trusted authority. That world is comfortable because it has two hidden gifts. First, there is shared memory: any two processes can be handed the same physical RAM and instantly see each other's writes. Second, there is a shared clock: one hardware timer drives the whole machine, so 'before' and 'after' are never in doubt. We are about to give both gifts away.
We do it because one machine is not enough. We want to serve more users than a single box can handle, so we add machines and spread the load. We want our service to keep running when a machine catches fire, so we keep copies elsewhere. We want data to live near the people who use it, scattered across the globe. A distributed system is many independent computers, connected only by a network, cooperating to look like one coherent service. The prize is scale, survival, and reach; the price is that the two gifts are gone.
The two gifts you just lost
Lose shared memory and you lose your favourite tools. Back in the concurrency rung a thread protected shared data with a semaphore — wait(S) before touching it, signal(S) after — and a mutual-exclusion lock kept two threads out of the same critical section. Every one of those tricks assumed one memory both parties could touch. Across machines there is no such memory. The only way machine A tells machine B anything is to send a message over the network, the discipline we call message passing. You cannot peek into another machine's RAM; you can only ask, and wait for an answer that may never come.
Lose the shared clock and you lose the meaning of 'when'. Each machine has its own quartz crystal ticking at its own slightly-wrong rate, drifting away from its neighbours by milliseconds a day. So if machine A stamps an event at 10:00:00.100 and machine B stamps another at 10:00:00.090, you genuinely cannot conclude B happened first — their clocks simply disagree. There is no global 'now' to consult. This single fact wrecks any algorithm that quietly assumed a total order of events, and repairing it is the whole reason logical clocks exist, which guide 4 of this rung is devoted to.
Delay, loss, and the cruellest one: partial failure
Messages take time, and the time is not fixed: a packet might arrive in a millisecond or in a second, depending on congestion and routing. Messages also get lost — a switch overflows, a cable is yanked — so 'I sent it' does not mean 'it arrived'. These hazards are why distributed programmers warn each other about the fallacies of distributed computing: tempting lies like 'the network is reliable', 'latency is zero', and 'bandwidth is infinite'. Believing any of them ships code that works on your laptop and falls apart in production.
But the deepest difficulty is partial failure, and it has no equivalent on one machine. On a single computer, things tend to fail all-or-nothing: either the machine is up and your code runs, or it crashes and everything stops together. In a distributed system, one node can die while the rest keep going. Worse, when you send a request to a node and hear nothing back, you cannot tell which of three things happened: the node crashed; the node is fine but slow; or the node did the work perfectly and only the reply got lost. This ambiguity — a silence that could mean any of these — is the single hardest fact in the whole field.
Client sends a request to a Server, then waits ... client ---- request ----> server client <... silence .... (nothing comes back) What does the silence mean? Three indistinguishable cases: (a) server crashed before doing the work -> NOT done (b) server is alive but slow / overloaded -> maybe done later (c) server did the work, the REPLY was lost -> ALREADY done The client cannot tell (a), (b), (c) apart from silence alone. This is partial failure -- and it forces retries to be careful.
Shapes a distributed system takes
Given those hardships, how do we actually arrange the machines? The most common shape is the client-server model: some machines play server, holding the data and doing the heavy work, while others play client, sending requests and rendering results. Your web browser asking a web server for a page is the everyday picture. It is simple to reason about because authority is centralized — but that same centre is a bottleneck under load and a single point of failure if it dies.
The other shape spreads authority out. In the peer-to-peer model every machine is an equal peer, both asking and answering, with no privileged centre — think of file-sharing swarms where each downloader is also an uploader. Peers scale gracefully and have no single point of failure, but coordinating equals is genuinely harder: with nobody in charge, the peers must somehow agree among themselves. That agreement problem returns at the end of this rung as consensus, and its sharpest limit is the CAP theorem, the finale of guide 5.
Living with the loss: the toolkit ahead
The rest of this rung is a toolkit for surviving these losses, and each guide tackles one. The next one makes the network nearly invisible with the remote procedure call: you call a function and it quietly runs on another machine, as if it were local. Guide 3 lets machines share files over the network and asks the awkward question of caching: if every node keeps its own copy for speed, how do they stay consistent? Guide 4 rebuilds a usable notion of time without a shared clock, using the happened-before relation and logical clocks. Guide 5 confronts agreement itself: consensus, the CAP theorem, and surviving failure by keeping replicas.
Underneath several of those answers sits one quiet idea: replication — keeping the same data on more than one machine. Replication is how a distributed system survives partial failure: if one copy's machine dies, another copy answers. But replication is also the source of the deepest tension, because the moment you have two copies you must keep them in step, and keeping them in step needs communication, which we just admitted is slow and unreliable. That tension — copies for survival versus copies that disagree — is the thread running through every remaining guide.
One honest caution to carry forward: distributed does not automatically mean better. Adding machines multiplies the ways things can go wrong, and it cannot repeal physics — a request crossing an ocean will always cost tens of milliseconds. We go distributed when one machine truly cannot give us the scale, the survival, or the reach we need, and we pay for it in complexity with open eyes. Keep that honesty close; it is the same spirit in which earlier rungs admitted that paging trades external for internal fragmentation, and that a microkernel buys robustness with the cost of extra message-passing.