đ The Simple Version (ELI5)
Imagine youâre building a huge Lego city. Each block (service) needs to connect with others, share information, and keep working even if some blocks break. Advanced system design patterns are like the instruction manuals that tell you how to connect, share, and protect your Lego city so it grows smoothly and stays alive even when parts fail.
Design Patterns Overview
Distributed systems face challenges such as latency, partial failures, and data consistency. Design patterns provide proven solutions to these problems, enabling engineers to build systems that are scalable, faultâtolerant, and maintainable.
Event Sourcing
Instead of storing the current state, event sourcing stores a log of all stateâchanging events. The current state is rebuilt by replaying these events.
// Example: UserCreated event
const event = {
type: 'UserCreated',
payload: { id: 123, name: 'Alice' },
timestamp: Date.now()
};
// Persist event to event store
Benefits: auditability, easy rollback, and natural integration with CQRS.
Command Query Responsibility Segregation (CQRS)
Separates read and write operations into distinct models, allowing each to scale independently.
# Command side
def create_user(user_data):
# Write to write model
pass
# Query side
def get_user(user_id):
# Read from read model (e.g., materialized view)
pass
Saga Pattern
Manages longârunning transactions across microservices using a sequence of compensating actions.
- Local transaction in Service A
- Publish event to Service B
- If Service B fails, trigger compensation in Service A
Circuit Breaker
Prevents cascading failures by halting calls to a failing service after a threshold of errors.
func callWithCircuitBreaker(ctx context.Context, target func() error) error {
// Circuit breaker logic here
}
Bulkhead Isolation
Partitions resources so that a failure in one part does not affect others.
- Separate thread pools for different service groups
- Dedicated connection pools per database shard
Sharding & Consistent Hashing
Distributes data across multiple nodes to balance load and improve performance.
// Consistent hashing example
HashRing ring = new HashRing();
ring.addNode("node1");
ring.addNode("node2");
String shard = ring.getNode("user:123");
Microservice Mesh
Provides a dedicated infrastructure layer for service-to-service communication, handling routing, load balancing, and observability.
- Istio, Linkerd, Consul Connect
- Zeroâtrust communication via mutual TLS
Leader Election & Gossip Protocol
Ensures a single coordinator for tasks and propagates state changes efficiently.
- Raft, Paxos for leader election
- Gossip for membership and health checks
CAP Theorem Application
Balancing Consistency, Availability, and Partition tolerance based on business requirements.
- Choose CA for critical banking systems
- Choose AP for social media feeds
Distributed Transactions (2PC & 3PC)
TwoâPhase Commit (2PC) ensures atomicity across multiple resources. ThreeâPhase Commit (3PC) adds an additional phase to reduce blocking.
-- 2PC example
BEGIN;
-- Prepare phase
PREPARE TRANSACTION 'tx1';
-- Commit phase
COMMIT PREPARED 'tx1';
Read/Write Splitting & Cache Invalidation
Route read queries to replicas and write queries to primaries; invalidate caches on writes.
- Read replicas with readâthrough caching
- CacheâAside pattern for write operations
Dead Letter Queue
Captures messages that cannot be processed after retries, enabling manual inspection and reprocessing.
- Amazon SQS DLQ, Kafka DLQ
- Automated alerting for stuck messages
Putting It All Together
Designing a distributed system is like orchestrating a symphony. Each pattern is an instrument that contributes to the overall harmony. By combining event sourcing, CQRS, sagas, and robust failure handling, you can build systems that scale gracefully and recover quickly.
Next Steps
Start by mapping your systemâs requirements to the appropriate patterns. Prototype with a small subset, measure latency and failure rates, and iterate. Remember, the goal is not to apply every pattern, but to choose the ones that solve real problems for your use case.