Partial Failure and the Fallacies of Distributed Computing

Why distributed systems are hard: partial failure, unreliable networks, the eight fallacies of distributed computing, and crash to Byzantine failure models.

Intermediate 3 min read · Updated

A distributed system is one where a computer you didn't know existed can stop yours from working. The core difficulty is partial failure: some parts of the system work while others don't, and a node often can't tell whether a remote peer is slow, crashed, or cut off. The fallacies of distributed computing are eight assumptions that look reasonable on one machine and break across a network. Designing well starts with not making them.

Partial failure and uncertainty

On one machine, an operation usually either succeeds or the whole process crashes. Across a network, a request to another service can end in many ways, and the caller often can't distinguish them:

ClientNetworkServercharge ₹500delivered (or lost?)server may process, crash, or pauseOK (or lost?)client times out: did it happen?
After a timeout, the client can't know whether the request never arrived, the server crashed mid-way, or the work succeeded and only the reply was lost.

That uncertainty is why retries need idempotency, why timeouts are mandatory (see timeouts and retries), and why "exactly once" is so hard (see delivery guarantees).

The eight fallacies

FallacyRealityDesign response
The network is reliablePackets are lost, connections reset, switches failTimeouts, retries with backoff, idempotent operations, acknowledgements
Latency is zeroEach hop costs milliseconds; cross-region costs tens to hundredsAvoid chatty calls, batch, cache, put data near users
Bandwidth is infiniteLarge payloads saturate links and cost moneyCompress, paginate, send deltas, keep payloads small
The network is secureTraffic can be observed or tampered with, even internallyTLS everywhere, mutual authentication, zero-trust networking
Topology doesn't changeInstances come and go; IPs change; routes moveService discovery, health checks, no hard-coded addresses
There is one administratorMany teams, vendors and policies control parts of the pathClear contracts, defensive limits, observability across boundaries
Transport cost is zeroSerialisation, network egress and connection setup all cost CPU and moneyEfficient formats, connection reuse, colocating chatty services
The network is homogeneousDifferent hardware, protocols, versions and cloudsStandard protocols, versioned APIs, compatibility testing

Failure models

Distributed algorithms are designed against a failure model, a statement of what can go wrong. Weaker assumptions make algorithms harder but more realistic.

ModelWhat a faulty node may doTypical handling
Crash-stopStop and never returnSimplest model; rarely realistic on its own
Crash-recoveryStop, then restart, possibly losing in-memory statePersist state durably, e.g. with a write-ahead log; most databases and consensus systems assume this
OmissionFail to send or receive some messagesRetries, acknowledgements, timeouts
Timing (performance)Respond, but too slowly, e.g. long GC pausesTimeouts, leases with fencing
ByzantineBehave arbitrarily or maliciously: send wrong or conflicting dataByzantine fault-tolerant protocols; needed in blockchains and some aerospace systems, rarely inside one company's datacenter

A long garbage-collection or VM pause is the failure people forget: the node isn't dead, just frozen, and when it resumes it may act on stale beliefs, such as still thinking it's the leader. See leader election.

Timing assumptions

  • Synchronous systems have known upper bounds on message delay and processing time. Real networks don't.
  • Asynchronous systems have no timing bounds at all, which makes some problems impossible to solve deterministically. See FLP impossibility.
  • Partially synchronous systems behave synchronously most of the time but have periods of unbounded delay. This is the realistic model, and algorithms like Raft are safe always and live (make progress) when the network behaves.

Practical habits

  • Give every remote call a timeout and decide what happens when it fires.
  • Make operations safe to retry, and assume duplicates and reordering.
  • Detect failures with heartbeats and timeouts, knowing they can be wrong. See gossip and failure detection.
  • Prefer designs where nodes can make progress independently and reconcile later, when correctness allows.
  • Test failure: inject latency, drops and partitions. See chaos engineering.

Where it’s used

Payments

Uncertain outcomes after timeouts are resolved with idempotency keys and status queries, never blind retries.

Databases

Crash-recovery assumptions drive write-ahead logging and replication protocols.

Microservices

Timeouts, circuit breakers and service discovery address unreliable networks and changing topology.

In an interview

  • Explain partial failure and why a timeout doesn't tell you what happened.
  • Name a few fallacies and the design response to each.
  • State the failure model your design assumes (usually crash-recovery with partial synchrony).
  • Mention process pauses as a realistic, often-ignored failure.

Further reading