
The instructor is ready
Distributed Systems Fundamentals
Distributed Systems Fundamentals
An introduction to distributed systems, teaching core concepts, architecture, and challenges for beginners in software engineering.
My workspace30 minFree to watch
What you’ll learn
- 01Introduction to Distributed SystemsWelcome. In this course, we’re going to explore the foundations of distributed systems. Our goal is to understand how multiple independent computers cooperate to appear as a single, coherent service. We’ll begin with a definition: a distributed system is a collection of autonomous computing elements that presents itself to users as one unified system. Why do we build them? For scalability, fault tolerance, shared resources, and hiding latency. You already interact with them every day through web search, online banking, multiplayer games, streaming platforms, and ride-sharing apps. Under the hood, these systems face three core challenges: concurrency of components, the lack of a single global clock, and independent failures of nodes. In 2026, these fundamentals are more critical than ever, forming the backbone of AI grids, edge computing, and federated orchestration. Next, we’ll examine the system models and communication paradigms that make this collaboration possible.
api.pageplace.degwdistsys20.github.iocs.vu.nl+21 min - 02System Models and Communication ParadigmsNow let's ground those concepts in concrete models. We begin with system models. A synchronous system assumes known bounds on processing and message delays. An asynchronous system has no such bounds, which makes it harder to reason about. In practice, most systems operate under partial synchrony, where things are well-behaved most of the time but occasionally break those bounds. We also need to define failure models. A crash-fault means a node simply stops. An omission fault means it fails to send or receive some messages. The most challenging is Byzantine, where a node behaves arbitrarily, even maliciously. Next, communication. The fundamental primitive is message passing. Built on top of that, we have Remote Procedure Calls, or RPC, which make a remote function look local. When we send data, we must serialize it. Common formats include human-readable JSON, and high-performance binary formats like Protobuf and Avro. Architecturally, we have three main paradigms. Client-server is the most common, with a central authority. Peer-to-peer distributes the load and responsibility. And publish-subscribe decouples producers from consumers with an event bus. Finally, a key philosophical point called the end-to-end argument. It states that application-level guarantees are often more robust than network-level ones. For example, TCP can retransmit lost packets, but an application-level retry is what actually confirms a business transaction completed. Middleware hides the underlying heterogeneity, presenting the distributed system as a single coherent entity. This sets the stage for our next topic, where we'll explore the core trade-offs through the CAP Theorem and Consistency Trade-Offs.
api.pageplace.degwdistsys20.github.iocs.vu.nl+22 min - 03The CAP Theorem and Consistency Trade-OffsLet's look at the practical framework for consistency trade-offs, starting with the CAP theorem. During a network partition, a distributed system must choose: linearizability, meaning every read sees the latest write, or availability, where every request gets a non-error response. Partition tolerance is mandatory, so the real choice is between C and A. Outside of a partition, you can have both. But CAP is best used as a per-operation design prompt, not a global system label. Ask yourself: for this specific operation, during a partition, is it more important to be correct or to be available? The PACELC extension adds that even during normal operation, we trade off latency against consistency. In practice, systems like ZooKeeper and etcd are CP, prioritizing consistency, while Cassandra and DynamoDB are AP, prioritizing availability. Next, we'll explore consistency models and conflict resolution in more detail.
rahulsuryawanshi.comcodelit.iofrontendtechlead.com+21 min - 04Consistency Models and Conflict ResolutionNow let's talk about consistency models and how we resolve conflicts. Consistency is not a simple on/off switch; it is a spectrum. At the strongest end, we have linearizability, where every read returns the most recent write. As we move down the spectrum, we pass through sequential and causal models, all the way to eventual consistency. For user-facing apps, we often find practical value in the middle with session guarantees like read-your-writes, where a user always sees their own updates, or monotonic reads, which prevent time from appearing to go backward. When conflicts happen, we need resolution strategies. Last-write-wins is the simplest, but it can silently drop data. We can use custom merge functions, or leverage vector clocks to track causality. A more sophisticated approach is the Conflict-free Replicated Data Type, or CRDT. These are data structures like counters and sets that are mathematically guaranteed to converge across replicas without any coordination. Finally, let's look at quorum math. A common rule is that the read quorum plus the write quorum must be greater than the replication factor. This ensures read freshness, but on its own, it does not guarantee linearizability. Next, we will explore timing, ordering, and coordination.
rahulsuryawanshi.comcodelit.iofrontendtechlead.com+22 min - 05Timing, Ordering, and CoordinationNow let's turn to the challenge of timing, ordering, and coordination. In a single machine, a global clock makes decisions easy. In a distributed system, no single clock exists. Physical timestamps drift and are unreliable for deciding what happened before what. Lamport timestamps give us a way to track happened-before relationships, and vector clocks go further by capturing causality. When nodes must act as one, we need leader election and mutual exclusion. Systems like ZooKeeper and etcd provide the building blocks: they offer locks, configuration management, and group membership. To detect failures without perfect synchrony, we rely on leases and heartbeats. A lease says a node is trusted for a limited time. A heartbeat checks if a peer is still alive. This is the foundation for making a group of nodes cooperate reliably. Next, we'll look at replication strategies and patterns.
rahulsuryawanshi.comcodelit.iofrontendtechlead.com+21 min - 06Replication: Strategies and PatternsNow let's turn to the architectural core of replication: the strategies and patterns that shape how replicas coordinate. Replication is what gives us higher availability, fault tolerance, and the ability to scale out reads. The three broad architectural families we work with are single-leader, multi-leader, and leaderless. The choice between them is fundamental. We also face a key operational decision with every write: synchronous replication ensures durability by confirming the write on all replicas before acknowledging the client, while asynchronous replication cuts write latency by acknowledging immediately and propagating the change in the background. A practical consistency challenge we often encounter is read-after-write consistency. If a user writes data and then immediately reads it back, they should see their own change. We solve this by routing reads to the primary replica or by using session guarantees. In the real world, we see these patterns everywhere: MySQL Group Replication and MongoDB replica sets implement single-leader architectures, while Redis and cloud-native databases often push toward more leaderless designs. All of these trade-offs prepare us for the central challenge of distributed agreement, which we'll tackle next in the consensus problem with Paxos and Raft.
rahulsuryawanshi.comcodelit.iofrontendtechlead.com+22 min - 07The Consensus Problem: Paxos and RaftNow let's address the consensus problem. When multiple nodes must agree on a single value despite failures, we turn to consensus protocols. Paxos was the classic solution, defining roles like proposers, accepters, and learners, but its practical implementation is notoriously difficult. Raft emerged as a direct answer to that complexity, designed for understandability. It decomposes consensus into leader election, log replication, and safety, making it the backbone of many production systems. To improve performance, Multi-Paxos and dynamic reconfiguration were developed, though they come with common operational pitfalls. At the extreme scale of Cloudflare's global network, QuePaxa, which we call Meerkat, takes a leaderless approach. It avoids the timeout tyranny of traditional protocols, allowing any replica to drive progress. You'll see these ideas in production everywhere: etcd uses Raft to underpin Kubernetes, CockroachDB relies on it for distributed SQL, while Spanner and Chubby demonstrate the power of consensus at Google's planetary scale. Next, we will bridge consensus and application logic by examining distributed transactions and concurrency control.
rahulsuryawanshi.comcodelit.iofrontendtechlead.com+22 min - 08Distributed Transactions and Concurrency ControlNow, when a single business transaction touches multiple services, each with its own database, we immediately lose the local ACID guarantees we rely on. Traditional approaches like Two-Phase Commit, or 2PC, try to solve this with a coordinator, but the protocol blocks if the coordinator fails. That is rarely acceptable in production microservices. Three-Phase Commit, or 3PC, is non-blocking in theory, but its complexity and edge cases keep it out of practical use. Instead, we turn to patterns that avoid global locking altogether. Optimistic Concurrency Control, or OCC, and Google’s Percolator show that large-scale transactions can work by detecting conflicts late and retrying, rather than holding locks early. For long-running workflows, the most common pattern is the Saga. Sagas break the work into a sequence of local transactions, each with a compensating transaction to undo the business effect if a later step fails. That brings us to our next topic.
rahulsuryawanshi.comcodelit.iofrontendtechlead.com+22 min - 09The Saga Pattern in PracticeNow let's bring the Saga pattern to life and see how we actually build one. Think of a Saga as a chain of local transactions. Each step commits independently in its own service, so there are no global locks and no XA coordinator to bottleneck us. If a later step fails, we don't roll back the database. Instead, we run a compensating transaction, a new piece of business logic that semantically undoes the earlier work, like issuing a refund instead of deleting a payment record. We have three kinds of steps. Compensable transactions can be undone. A pivot transaction is the point of no return, as soon as we charge the credit card, we must move forward. Retriable transactions come after the pivot. They are idempotent and we just keep retrying them until they succeed. We also have two coordination styles. Choreography uses peer events, each service listens and reacts. Orchestration uses a central state machine that calls each service and manages the flow. To make this reliable in production, we need a few must-haves. We pair every saga with the transactional outbox pattern so events are never lost, we use idempotency keys so retries are safe, we mark in-progress records with semantic locks to avoid dirty reads, and we persist the saga state for recovery. That's the practical blueprint. Next, we'll shift gears and look at scalability and partitioning.
singhajit.commicroservices.iothemainthread.beehiiv.com+22 min - 10Scalability and PartitioningNow let's turn to scalability and partitioning. When we talk about scaling, we mean vertical and horizontal approaches. Vertical scaling adds more power to a single machine, but Amdahl's Law and the Universal Scalability Law remind us that serial bottlenecks limit how far that can go. Horizontal scaling distributes work across many nodes, and we combine that with functional decomposition, breaking the system into microservices, and data partitioning, spreading data across those nodes. We choose sharding strategies based on access patterns. Key-range sharding groups data by value, hash-based sharding provides uniform distribution, and directory-based sharding adds a lookup layer for flexibility. When the topology changes, consistent hashing becomes critical because it minimizes the amount of data that must be remapped, avoiding a system-wide reshuffle. Even with good sharding, hot spots can still emerge from uneven workloads. We mitigate them with key salting, which spreads a popular key across multiple partitions, dynamic rebalancing to redistribute data, and caching patterns that absorb repeated reads. Those techniques turn a partitioned system into one that can scale elastically. Next, we'll bridge these scalability concepts into reliability with our discussion of reliability, fault tolerance, and resilience patterns.
rahulsuryawanshi.comcodelit.iofrontendtechlead.com+22 min - 11Reliability, Fault Tolerance, and Resilience PatternsIn this slide, we explore the patterns that keep distributed services running when components fail. We start with failure detectors. A perfect detector correctly identifies every crash, but that is impossible in a purely asynchronous system. In practice, we use eventually perfect detectors that may suspect a live node temporarily but eventually converge on the right answer. Next, we prevent cascading failures. A circuit breaker stops sending requests to a failing downstream service, a bulkhead isolates failures to a limited pool of resources, and retries with exponential backoff avoid overwhelming a recovering system. For exactly-once semantics, we combine idempotency keys with database constraints. The idempotency key lets the system recognize a duplicate request, and the constraint rejects the duplicate at the storage layer. We also choose load balancing strategies carefully. Round-robin is simple, least connections handles uneven loads, and consistent hashing minimizes re-mapping when the server pool changes. Finally, chaos engineering tests these patterns deliberately. Tools like Litmus, Chaos Mesh, Gremlin, and others let us inject failures in a controlled way to verify our resilience claims before a real incident does. Next, we will look at Chaos Engineering in the 2026 Ecosystem.
rahulsuryawanshi.comcodelit.iofrontendtechlead.com+22 min - 12Chaos Engineering in the 2026 EcosystemNow let's explore how chaos engineering has evolved in practice. The goal is systematic resilience testing: we inject failures to uncover weaknesses before real incidents do. The ecosystem includes CNCF projects like LitmusChaos and Chaos Mesh, alongside enterprise platforms such as Gremlin, Steadybit, and Harness. A new wave of developer-friendly tools has also emerged. Entropy offers an agentless architecture using ephemeral containers. Tumult is a Rust-native platform with built-in OpenTelemetry and embedded DuckDB analytics. Pastaay and Krkn further round out the space. We are also seeing AI-assisted chaos. Tools autonomously generate experiments, perform SLO-aware fault injection, and evolve scenarios using fitness functions. Perhaps most importantly, chaos engineering is shifting from isolated GameDays to continuous integration pipelines, where experiments run as standard practice in every deployment. Next, we will connect these resilience patterns to Observability and Debugging in Distributed Deployments.
github.comgithub.comgithub.com+22 min - 13Observability and Debugging in Distributed DeploymentsWe have discussed how to build scalable systems. Now let us shift to understanding what they are doing in production. Observability and debugging are where distributed systems theory meets daily operations. Metrics tell us the 'what', like a spike in latency. Traces reveal the 'why' across services. To make that work, W3C Trace Context propagates the trace ID between services, and we must be careful not to break it at load balancers or message queues. Tail-based sampling is a key architectural decision. It lets us keep one hundred percent of errors and slow traces while dropping most fast, successful ones, balancing cost and visibility. We also inject the trace ID and span ID into logs. This gives us full-context debugging, linking a single error message to the entire request path. For proactive alerting, we rely on RED metrics: Rate, Errors, and Duration. These drive alerts that catch issues before users notice. Next, we will explore modern architectural patterns and infrastructure.
2 min - 14Modern Architectural Patterns and InfrastructureNow, let's pull these concepts together by looking at modern architectural patterns and infrastructure. At the edge, functions and databases like Cloudflare D1 or Turso are redefining deployment with sub-millisecond cold starts. This is paired with WebAssembly, whose WASI 0.3 and Component Model standards enable polyglot, sandboxed microservices running directly on the network edge. For internal traffic, service meshes like Istio and Linkerd offload critical resilience logic, including retries, circuit breaking, and detailed observability, freeing developers to focus on business logic. Event-driven patterns are also evolving. We are seeing mature implementations of event sourcing and CQRS, alongside durable execution platforms like Google's Agent Executor, which can automatically resume complex, long-running workflows. Finally, AI is beginning to orchestrate the infrastructure itself. We have NVIDIA's AI Grid for intelligent inference placement, and federated Kubernetes projects like k0smos and the CODECO framework, which coordinate workloads across geographically dispersed clusters. The line between application logic and infrastructure is getting thinner, and these patterns are the proof. Next, we'll move to our final topic: Key Takeaways and Further Learning.
github.comgithub.comgithub.com+22 min - 15Key Takeaways and Further LearningThat brings us to the end of our introduction to distributed systems. Let's quickly pull together the key themes. We started with the textbook definition: concurrency, no global clock, and independent failures. Those three characteristics directly inform every design decision we discussed. For every operation, we learned to ask three questions. What is our failure model? Which consistency guarantee do we need, specifically linearizability versus something weaker? And what happens during a network partition? The CAP theorem taught us that choice is mandatory, not optional. We also built out a practical toolbox. Consensus protocols like Raft, replication, sharding, the Saga pattern for cross-service workflows, distributed tracing, and chaos engineering. These are not just academic concepts. They are the techniques we use to build reliable systems. Finally, remember that the foundational papers, Dynamo, Raft, Spanner, and others, provide lasting mental models. They are worth your time. To continue learning, explore the CNCF landscape, the Papers We Love community, and the MIT 6.5840 course. Thank you for joining me. Now, go build systems that are safe, available, and a pleasure to operate.
rahulsuryawanshi.comcodelit.iofrontendtechlead.com+22 min
Sources consulted
Web sources consulted while building this course.
- 9781447930174.pdf — api.pageplace.de
- Distributed Systems — gwdistsys20.github.io
- A brief introduction to distributed systems - Computer Science — cs.vu.nl
- Distributed Systems | Pearson eLibrary — elibrary.pearson.de
- DISTRIBUTED SYSTEMS — sisis.rz.htw-berlin.de
- CAP Theorem Explained for Distributed Systems — Correctly - Rahul Suryawanshi — rahulsuryawanshi.com
- CAP Theorem Explained — A Practical Guide to Distributed System Trade-offs — Codelit.io — codelit.io
- CAP Theorem Explained - System Design Tutorial | TechLead | TechLead — frontendtechlead.com
- CAP theorem explained: interactive visualisations of consistency vs. availability | The Computer Science Book — thecomputersciencebook.com
- The CAP Theorem, Consistency Models, and the Trade-Offs Nobody Warns You About | Charles Sieg — charlessieg.com
- Saga Pattern Explained: Distributed Transactions for Microservices - Ajit Singh — singhajit.com
- Pattern: Saga — microservices.io
- The Saga Pattern: Distributed Transactions Without 2PC — themainthread.beehiiv.com
- Saga Design Pattern - Azure Architecture Center — learn.microsoft.com
- The Saga Pattern: Managing Distributed Transactions Without Losing Your Mind – The Dev World – Sergio Lema — sergiolema.dev
- ibrahimkizilarslan/entropy — github.com
- faultbox/Faultbox — github.com
- mwigge/tumult — github.com
- litmuschaos/litmus — github.com
- Best Chaos Engineering Tools Reviews 2026 — gartner.com