Complex Systems · Phase 4: High-Level Design (HLD)
Distributed Key-Value Store (Amazon Dynamo & Cassandra)
Build a Dynamo-style key-value store while separating quorum intersection from database guarantees, then trace hints, read repair, anti-entropy, tombstones, and recovery load.
Primary specification: Dynamo: Amazon’s Highly Available Key-value Store (DeCandia et al.)
Lesson 31 of 33
1d streakThe Architectural Question
Network partitions in multi-datacenter clusters cause replica nodes to diverge; without anti-entropy mechanics, stale reads persist indefinitely.
Core Engineering Objectives
- Consistent hashing and placement across independent failure domains
- Quorum intersection math and the additional assumptions required for strong consistency
- Anti-entropy and conflict reconciliation: Vector clocks, Hinted Handoff for temporary partitions, and background Merkle trees
1. Define the Key-Value Contract Before Choosing Algorithms
1. Client
Sends a key, value, and consistency preference.
2. Coordinator
Hashes the key and selects replica owners.
3. Replicas
Persist the version and return acknowledgements.
4. Quorum
Completes when the configured response threshold is met.
5. Repair
Reconciles divergent versions in the background or on reads.
Replication improves availability; conflict detection and repair define what happens after concurrent or missed writes.
A distributed key-value store exposes operations such as PUT(key, value), GET(key), and DELETE(key) while spreading data across machines. The hard questions are not the method names: who owns a key, how many replicas acknowledge an operation, what a read may return during failure, how conflicting versions are resolved, and how replicas converge afterward.
Replication factor N
The number of replicas intended to hold a key.
Write acknowledgment W
How many replica acknowledgments the coordinator waits for before reporting success.
Read acknowledgment R
How many replica responses are consulted before returning a value.
Quorum intersection
If the same replica set is used and R + W > N, every read and write quorum overlap in at least one replica.
Overlap Is Not the Whole Consistency Proof
2. Choose Availability and Consistency Per Operation
| Workload | Possible policy | Trade-off |
|---|---|---|
| Shopping cart | Accept writes during replica failure; merge versions | Availability is favored; clients may reconcile concurrent carts |
| Session lookup | LOCAL_QUORUM in one region | Predictable local consistency with regional failure limits |
| Feature flags | Versioned values and monotonic reads | Stale flags may be acceptable briefly, rollback must be explicit |
| Money balance | Use a transactional/consensus-backed system | A Dynamo-style eventually consistent register is the wrong primitive |
Use it when
Use a Dynamo-style store for partitionable key access, high availability, simple per-key values, and an application-defined conflict policy.
Reconsider when
Use a relational or consensus-backed transactional store when correctness spans keys, uniqueness is global, or stale/conflicting values would violate a business invariant.
3. Size User Traffic and Repair Traffic Separately
Given 500,000 operations/s at peak, 70% reads, 30% writes, 1 KiB values, replication factor 3, and a target of 60% steady-state utilization, derive a starting point. These numbers are illustrative and must be benchmarked with the chosen consistency level and value distribution.
| Dimension | Arithmetic | Result |
|---|---|---|
| Peak reads | 500k × 70% | 350k reads/s |
| Peak writes | 500k × 30% | 150k writes/s |
| Replica write operations | 150k × N=3 | 450k replica writes/s |
| Logical payload ingress | 150k × 1 KiB | ≈154 MB/s |
| Replicated payload ingress | 154 MB/s × 3 | ≈461 MB/s before protocol/compaction |
| Raw capacity per 100 TB logical | 100 TB × 3 / 0.60 | ≈500 TB before repair headroom |
Background compaction, anti-entropy repair, streaming, tombstones, and read repair compete with foreground requests. A node count based only on client QPS will fail during recovery—the exact moment the system has fewer healthy nodes.
4. Route, Replicate, and Coordinate
- 01Partitioner: hashes the key into a token range; virtual nodes or an equivalent placement scheme distribute ownership.
- 02Preference list: selects N replicas across failure domains, not merely the next N processes on one rack.
- 03Coordinator: accepts any client request, forwards it to replicas, and waits for the requested consistency level.
- 04Storage engine: appends writes to a commit log and memtable, then flushes immutable sorted tables.
- 05Repair mechanisms: hints shorten inconsistency after brief outages; read repair fixes replicas observed by reads; scheduled anti-entropy repair covers the full dataset.
- 06Membership and topology: expose node state, token ownership, rack/zone placement, and safe bootstrap/decommission workflows.
Architectural Boundary · Do Not Confuse
Strict quorum
Sloppy quorum
Strict quorum waits for replicas from the intended set, preserving straightforward overlap but may reject during failure. Dynamo-style sloppy quorum writes to reachable fallback nodes to remain available, then uses hinted handoff; the read/write sets may not intersect as a simple R + W > N argument assumes.
5. Make Versions and Deletes First-Class
RECORD
key
value
version vector/version metadata or database timestamp
tombstone true for a logical delete
expires_at optional TTL
WRITE RESULT
acknowledged_by
version
READ RESULT
value | siblings | not_found
version
INVARIANTS
a retry with the same operation_id does not apply the mutation twice
a tombstone remains until every relevant replica can learn the delete
conflict resolution is deterministic and documented
placement spans independent failure domainsDeleting a Tombstone Too Early Resurrects Data
6. Trace One Write and One Read
function put(key, value, consistency):
replicas = placement.preferenceList(hash(key), N=3)
version = nextVersion(readContextOrClock())
send mutation(key, value, version) to every replica
wait until consistency.requiredAcks arrive
return success(version) or timeout(unknownOutcome=true)
function get(key, consistency):
replicas = placement.preferenceList(hash(key), N=3)
responses = read enough replicas for consistency
versions = reconcile(responses)
if one version dominates: return it and repair stale participants
if versions are concurrent: apply documented merge or return siblings
return resultA write timeout is an unknown outcome, not proof of failure: some replicas may have stored it. Clients retry with an idempotency token or version precondition. Reads compare version metadata, not arrival time at the coordinator.
7. Understand How Replicas Actually Converge
| Mechanism | When it helps | Limit |
|---|---|---|
| Hinted handoff | A replica is temporarily unavailable during a write | Best effort and time bounded; not a replacement for repair |
| Read repair | A read observes divergent replicas | Only touches replicas and data involved in that read |
| Anti-entropy repair | Scheduled comparison finds cold divergent ranges | Consumes CPU, disk, and network; must finish within operational windows |
| Merkle tree | Narrows mismatched ranges before streaming | Tree agreement depends on comparable range snapshots and repair implementation |
Recovery Can Become the Outage
8. Make the Trade-offs Observable
Track latency and errors by operation and consistency level, not one cluster average. Add coordinator timeouts, unavailable responses, replica divergence, oldest unrepaired range, hint age/volume, tombstone scans, compaction backlog, disk imbalance, and cross-zone bytes. An availability number without the requested consistency level is incomplete.
Documented Cassandra Detail
9. Active Recall
Active Recall Checkpoint
For N=3, why does R=2 and W=2 create quorum intersection, and why is that not automatically linearizability?
Show answer & explanation
Any two subsets of size two from the same three replicas overlap in at least one node. But linearizability also depends on replica-set membership, ordering, concurrent-write resolution, coordinator behavior, and database semantics. Sloppy quorums or timestamp-based conflict resolution can invalidate the simplified proof.
Active Recall Checkpoint
Why are hints insufficient as the only repair mechanism?
Show answer & explanation
Hints are temporary, coordinator-owned, and best effort. They may expire or be lost, and they cover missed writes known to that coordinator. Scheduled anti-entropy repair compares replica ranges and is required to find cold divergence.
Topic sizing snapshot
The four numbers that materially affect this architecture. Use them as bounds, not as a generic calculator embedded in every lesson.
Peak QPS
500,000 QPS aggregate read/write
5-Yr Storage
100 TB logical becomes ~500 TB provisioned at RF=3 and 60% target utilization
Bandwidth
~3.7 Gbps replicated payload ingress before protocol, repair, and compaction
Working Set RAM
Benchmark memtables, indexes, cache, and compaction headroom per node
Architectural Trade-Off Analysis
Compare latency, throughput, consistency, and operational complexity across core industry alternatives.
Architecture Decision Matrix
Multi-axis engineering evaluation and FAANG interview rules of thumb.
SQL (Postgres / MySQL)
Relational ACID Store
Structured schema, relational joins, ACID transactions, and strict foreign keys.
NoSQL (Cassandra / DynamoDB)
Distributed Non-Relational Store
Horizontal partition keys, denormalized documents/wide-columns, and tunable consistency.
| Evaluation Axis | SQL (Postgres / MySQL) | NoSQL (Cassandra / DynamoDB) | Details |
|---|---|---|---|
Latency | Moderate | Strong | |
Throughput | Moderate | Strong | |
Scalability | Moderate | Strong | |
Consistency | Strong | Moderate | |
Complexity | Strong | Moderate | |
Cost | Moderate | Strong |
When to Choose in an Architecture Interview
Choose SQL when ACID guarantees are non-negotiable (financial ledgers, payment processing, inventory checkout) or when query access patterns are unpredictable and require ad-hoc analytical joins.
Choose NoSQL when write volume exceeds single-node capacity (>20K writes/sec), data is unstructured/hierarchical (logs, telemetry, user feeds), or multi-region active-active replication is mandatory.
Never say "NoSQL is faster than SQL" without qualification. SQL with proper B-Tree indexes on indexed primary keys is lightning fast. NoSQL wins on horizontal write scaling, not inherent single-row read speed.
Production Postmortem & Verification
Production Incident Postmortem
- Trigger / Setup: A key-value cluster operates with N=3, R=1, W=1 to maximize throughput and minimize latency.
- Production Symptom: Users consistently read stale account profiles after updates, and network partitions lead to permanent silent data divergence.
- Root Cause & Fix: Choose a documented consistency level for critical paths and run scheduled anti-entropy repair; hints and read repair are not complete substitutes.
Acceptance Criteria & Outcomes
- Formulate quorum consistency equations and analyze trade-offs between R=1, W=3 vs R=2, W=2 vs R=3, W=1.
- Explain how Hinted Handoff preserves write availability during transient node outages.
- Trace Merkle tree comparison algorithms for detecting diverging replica data with minimal network payload transfer.
End-of-Chapter Synthesis & Key Takeaway
Distributed Key-Value Store (Amazon Dynamo & Cassandra) is built around one fundamental rule: Establish clear responsibility and explicit trade-offs.. Before adding components, establish explicit quantitative SLAs for latency, throughput, and consistency. Choose the simplest architecture that meets stated constraints.
Architectural & Technical Interview Review
Core FAANG Interview Questions
Q01How do you justify introducing Distributed Key-Value Store (Amazon Dynamo & Cassandra) into a high-scale production architecture?Click to reveal model answer →Hide answer ↑Requirements & Design Brief
Introduce Distributed Key-Value Store (Amazon Dynamo & Cassandra) only when measured scale, data size, or failure boundaries exceed single-node capacity. State the exact bottleneck, evaluate operational overhead, and verify that the trade-offs justify the added moving parts.
Q02What is the primary trade-off and hidden operational cost of Distributed Key-Value Store (Amazon Dynamo & Cassandra)?Click to reveal model answer →Hide answer ↑Architecture Trade-offs
It improves scalability and availability, but introduces network hops, serialization overhead, and eventual consistency or coordination complexity.
Q03How do you handle catastrophic failure or dependency degradation in Distributed Key-Value Store (Amazon Dynamo & Cassandra)?Click to reveal model answer →Hide answer ↑Failure Review & Recovery
Implement connect/read timeouts, exponential backoff with jitter, and fallback defaults so downstream degradations do not cause cascading outages.
Production Pitfalls & Anti-Patterns
Critical Failure Anti-Patterns
Premature Distributed Complexity
Scattering distributed components before identifying concrete write, read, or storage limits creates accidental points of failure and operational debt.
Production Mitigation: Start with the simplest modular design that satisfies requirements, evolving it only as measured constraints dictate.
Unbounded Retries and Cascading Storms
When a dependency degrades, immediate synchronized retries multiply downstream traffic, turning a minor slowdown into a total fleet outage.
Production Mitigation: Enforce strict retry budgets, exponential backoff, and full randomized jitter on all client calls.
Neglecting Observability and Metrics
Deploying architecture without distributed tracing or p99 tail latency alerts leaves engineers blind when partial partitions occur.
Production Mitigation: Export metrics for request rate, error rate, p95/p99 duration, and saturation at every service boundary.