A distributed system is a collection of independent computers that appears to its users as a single coherent system. This definition, while simple, captures the central tension of the field: the computers are independent, meaning they can fail, be slow, or disagree with one another; yet the system as a whole must present a unified, reliable, and useful service. Distributed systems is the discipline of designing, building, and reasoning about such collections. It is not a single technique but a body of problems, principles, and engineering practices that arise whenever computation is spread across multiple machines connected by a network.
The fundamental difficulty of distributed systems stems from two physical facts. First, there is no shared memory: each computer has its own local state, and communication happens only by sending messages over a network. Second, there is no global clock: each machine has its own clock, and these clocks drift relative to one another. These two facts mean that no process can know the state of another process at a given instant, nor can it know the exact order of events across the system.
This leads to the field's central questions. How can processes coordinate their actions when they cannot observe each other directly? How can a system remain correct when messages can be delayed, lost, duplicated, or reordered? How can it continue to function when some of its computers crash? How can it present a consistent view of data when copies of that data live on different machines? These questions are not merely theoretical; they have direct practical consequences for the performance, availability, and correctness of nearly every large-scale software system in use today.
The intellectual roots of distributed systems lie in the 1970s, when computer networks first made it possible to connect multiple machines. Early work focused on connecting terminals to mainframes and on file transfer between computers. The term "distributed system" itself came into use in the late 1970s and 1980s, as researchers began to ask what it would mean for a collection of machines to act as a single, integrated computing resource.
A crucial early development was the study of distributed algorithms: procedures that run concurrently on multiple machines and coordinate through message passing. In 1978, Leslie Lamport introduced the concept of logical clocks, a way to assign a partial ordering to events in a distributed system without relying on physical time. This work laid the foundation for understanding causality and ordering, which remains central to the field. Around the same time, researchers began to formalize the problem of consensus: getting multiple processes to agree on a single value, such as which process should be the leader or what the next state of a replicated database should be.
The 1980s saw the rise of the "Byzantine generals problem," which asked how processes could reach agreement even when some of them might be malicious or behave arbitrarily. This work, along with the study of crash failures, produced a rich body of impossibility results. The most famous of these is the FLP result (named after Fischer, Lynch, and Paterson, 1985), which proved that in an asynchronous system—one where messages can be delayed arbitrarily—no deterministic algorithm can guarantee consensus if even a single process can crash. This result is often misunderstood as saying consensus is impossible; in practice, it means that algorithms must use timeouts, randomization, or other mechanisms to make progress in real systems.
The 1990s and 2000s brought distributed systems into the mainstream of computing. The rise of the web, and later cloud computing, meant that virtually every large service—search engines, social networks, e-commerce, banking—was built as a distributed system. This period saw the development of practical techniques for replication, consistency, and fault tolerance, as well as the creation of widely used infrastructure such as distributed file systems, key-value stores, and message queues. The field shifted from a primarily academic discipline to one with deep engineering practice, though the fundamental theoretical results continued to inform and constrain what was possible.
The field is organized less by rival schools than by a set of enduring design tensions. The most important of these is the trade-off between consistency and availability, often summarized by the CAP theorem. The CAP theorem states that a distributed data store cannot simultaneously provide all three of: consistency (every read returns the most recent write), availability (every request receives a response, even if some nodes have failed), and partition tolerance (the system continues to operate despite network failures that split it into isolated groups). Since network partitions are unavoidable in practice, designers must choose between consistency and availability when a partition occurs.
This trade-off has produced two broad families of systems. On one side are systems that prioritize consistency, often using a technique called consensus to ensure that all replicas agree on the order of operations. These systems, such as those built on the Paxos or Raft algorithms, provide strong guarantees: if a write is acknowledged, it will never be lost, and all readers will see the same data. The cost is that they may become unavailable during a partition, because they cannot safely proceed without a quorum of nodes. On the other side are systems that prioritize availability, often using a model called eventual consistency. These systems allow replicas to diverge temporarily, accepting writes on any node and reconciling differences later. They remain available during partitions but may return stale or conflicting data.
This consistency-availability tension is not a simple binary. Between the extremes of strong consistency and eventual consistency lies a spectrum of weaker consistency models, such as read-your-writes, monotonic reads, and causal consistency. Each model provides a different guarantee about what a client will observe, and each has different performance and availability characteristics. Choosing a consistency model is one of the most important design decisions in a distributed system, and it depends on the application's requirements. A banking system may require strong consistency for account balances, while a social media feed may tolerate eventual consistency for likes and comments.
Another major axis of design is the distinction between stateful and stateless systems, and between systems that replicate data versus those that partition it. Replication means keeping copies of the same data on multiple machines, which improves read performance and fault tolerance but requires coordination to keep copies consistent. Partitioning (also called sharding) means splitting data across machines, so that each machine holds a different subset. Partitioning improves scalability—more machines can hold more data—but makes operations that span multiple partitions more expensive and complex. Most large systems use both: they partition data to scale, and replicate each partition to tolerate failures.
A third major approach is the distinction between synchronous and asynchronous communication. In synchronous communication, a process sends a message and waits for a reply before continuing. This is simple to reason about but can waste time and resources. In asynchronous communication, a process sends a message and continues immediately, handling replies when they arrive. Asynchronous communication is more flexible and scalable, but it makes reasoning about ordering and failure much harder. Many systems use a hybrid: synchronous communication for critical operations, asynchronous for less critical ones.
A deep and recurring theme in distributed systems is the problem of ordering. Because there is no global clock, processes cannot simply timestamp events and compare them. Lamport's logical clocks provide a partial order: if event A causally precedes event B, then A's logical timestamp is less than B's. But logical clocks do not capture all orderings; two events that are causally unrelated may have arbitrary timestamps. Vector clocks extend logical clocks to capture causal history more precisely, at the cost of more storage and communication.
The problem of ordering is intimately connected to the problem of consistency. Strong consistency requires a total order on operations: every replica must apply operations in the same order. Consensus algorithms provide this total order by having replicas agree on a sequence of operations. Weaker consistency models relax this requirement, allowing different replicas to apply operations in different orders and reconciling later.
The ordering problem also appears in the design of distributed transactions. A transaction is a sequence of operations that must appear to execute atomically: either all of its effects are visible, or none are. In a distributed system, a transaction may touch data on multiple machines, and the system must ensure that the transaction commits or aborts atomically across all of them. This requires a distributed commit protocol, the most famous of which is two-phase commit. Two-phase commit has a known weakness: if the coordinator crashes, the transaction may be left in an uncertain state, and the system may need to block or use a more complex protocol to resolve it. This is one reason why many modern systems avoid distributed transactions altogether, preferring to design data models that keep related data on the same machine.
A defining characteristic of distributed systems is that failures are not exceptional; they are the norm. Machines crash, networks partition, messages are lost, and clocks drift. A well-designed distributed system must tolerate these failures without losing data or becoming unavailable.
The field has developed a taxonomy of failure models. The simplest is crash failure, where a process stops executing and never resumes. More severe are omission failures, where a process fails to send or receive a message, and Byzantine failures, where a process behaves arbitrarily, possibly maliciously. The Byzantine model is the most general and the most expensive to handle; algorithms that tolerate Byzantine failures require more replicas and more communication than those that tolerate only crashes. In practice, most systems assume crash failures and use techniques such as replication, heartbeats, and timeouts to detect and recover from them.
A well-known set of practical pitfalls, often called the "fallacies of distributed computing," captures the assumptions that novice designers make and that experienced designers know to avoid. These include assuming that the network is reliable, that latency is zero, that bandwidth is infinite, that the network is secure, that topology does not change, that there is one administrator, that transport cost is zero, and that the network is homogeneous. Each fallacy corresponds to a real failure mode in distributed systems, and much of the field's engineering practice is devoted to designing systems that are robust to these realities.
The present landscape of distributed systems is dominated by the infrastructure of cloud computing. Large-scale systems are typically built as collections of services, each running on many machines, communicating through well-defined interfaces. Container orchestration platforms manage the deployment and scaling of these services, while service meshes handle communication, security, and observability between them.
Data management has evolved into a rich ecosystem of specialized systems. Distributed databases offer a range of consistency guarantees, from strict serializability to eventual consistency. Key-value stores provide simple, highly scalable data access. Stream processing systems handle continuous flows of data, such as sensor readings or user events, and provide windowed computations over those flows. Message queues and publish-subscribe systems decouple producers and consumers, allowing components to communicate asynchronously.
A significant recent development is the rise of "serverless" computing, where the infrastructure hides the machines entirely and exposes only functions that are executed on demand. Serverless systems are distributed systems underneath, but the user does not manage the distribution; the platform handles scaling, fault tolerance, and placement. This represents a shift in who bears the complexity of distribution, but the underlying problems remain.
Another important trend is the increasing attention to consistency and correctness in practice. Tools for formal verification, such as model checking and theorem proving, have been applied to distributed algorithms and even to production systems. These tools can prove that an algorithm satisfies its specification under all possible interleavings of events, which is valuable because the space of possible behaviors in a distributed system is vast and difficult to test exhaustively.
The field also continues to grapple with the fundamental limits established by theory. The CAP theorem, the FLP result, and the lower bounds on the cost of consensus are not obstacles to be overcome but constraints to be designed around. A mature distributed systems engineer understands these limits and knows how to choose designs that work within them, rather than fighting them.
Despite decades of progress, the central questions of distributed systems remain open in a practical sense. How can we build systems that are both strongly consistent and highly available? How can we make distributed systems easier to reason about and verify? How can we manage the operational complexity of systems that span thousands of machines? How can we ensure security and privacy when data is spread across many locations and administrative domains?
These questions are unlikely to have final answers. Distributed systems is a field defined by trade-offs, and every new technology shifts the balance without eliminating the underlying tensions. What makes the field coherent is not a single method or school of thought, but a shared set of problems: coordination, ordering, replication, failure, and consistency. The concepts and techniques developed to address these problems—logical clocks, consensus, quorums, replication protocols, consistency models—form a durable intellectual toolkit that any practitioner of distributed systems must master.