TOPIC 03

Consistency & Availability Patterns

CAP tells you a trade-off exists. These patterns are how real systems actually make it — from "reads might lie for a moment" to "two datacenters, zero downtime."

Intermediate 30 min read 9 concepts

At a Glance

Consistency Patterns: How Stale Can a Read Be?

When data lives on multiple nodes, "what does a read return right after a write?" becomes a spectrum. Three useful points on it:

1. Weak consistency

After a write, reads may or may not ever see it. No promises. This sounds terrible until you realize it's perfect for real-time data where late information is worthless anyway: if you drop a few frames of a video call or a position update in a game, you want the newest data next, not a replay of the old.

Used by: VoIP, video chat, multiplayer game state, memcached under contention.

2. Eventual consistency

After a write, reads will see it eventually — typically within milliseconds to seconds — once replication catches up. The system converges to one truth, just not instantly.

Used by: DNS propagation, email delivery, S3 (historically), Amazon shopping carts, social media timelines.

Eventual consistency: a write ripples outward N1 N2 N3 reader sees new value reader sees old value… for now

N1 accepts the write instantly; N2 and N3 converge moments later. Readers in between may see history.

3. Strong consistency

After a write completes, every read sees it, everywhere. Achieved by synchronous replication, quorums, or routing all reads through the leader. The price is latency (you wait for replicas) and reduced availability (no majority → no service).

Used by: bank ledgers, payment systems, seat/inventory reservation, anything in an RDBMS transaction, Google Spanner.

PatternGuaranteeCostGreat for
WeakNone — best effortCalls, gaming, live telemetry
EventualConverges after replication lagBrief stalenessFeeds, carts, DNS, email
StrongReads always see latest writeLatency + availabilityMoney, inventory, transactions
Mix per feature, not per system

One product can use all three. An e-commerce site reads product pages eventually-consistently, tracks your cart eventually, and charges your card strongly. Pick the cheapest consistency each feature can tolerate.

Quorum: The Math Behind Distributed Consensus

How do replicated systems offer strong consistency without routing everything through one leader? Quorums. With N replicas, require W nodes to acknowledge each write and consult R nodes on each read. The magic inequality:

W + R > N # strong consistency: read & write sets MUST overlap

# Example: N=3, W=2, R=2 → W+R = 4 > 3
# Any 2 written nodes overlap any 2 read nodes
# → at least one node in every read has the latest write
N=3, W=2, R=2 — the overlap node always has the truth N1 N2 N3 write (W=2) read (R=2) N2 is in BOTH sets → the read is guaranteed to see the latest write W + R = 4 > N = 3

Whatever 2 nodes the write touches and whatever 2 nodes the read consults, at least one node is in both.

Tuning W and R lets you slide along the consistency/latency spectrum without changing the architecture:

Configuration (N=3)WritesReadsPersonality
W=2, R=2MediumMediumBalanced strong consistency
W=1, R=3Fast SlowWrite-heavy workloads, consistent reads
W=3, R=1SlowFast Read-heavy — like a CDN's profile
W=1, R=1FastFastW+R ≤ N → eventual consistency only

Cassandra exposes exactly this: you choose a consistency level (ONE, QUORUM, ALL) per query, which is just choosing W and R on the fly.

Vector Clocks — Tracking Causality

Distributed systems have no global clock — every machine's clock drifts, and NTP can only do so much. So how do you know which of two writes happened first, or whether they happened concurrently? Logical clocks.

The simplest logical clock is a counter each node increments on every event. A vector clock extends this: each node tracks a vector of counters, one slot per node — [A:2, B:1, C:0] means "I've seen 2 events from A, 1 from B, none from C."

# Vector clock rules (node A's perspective)
on local event:
 clock["A"] += 1

on send(message):
 clock["A"] += 1
 message.clock = clock # piggyback the vector

on receive(message):
 for node in all_nodes: # elementwise max
 clock[node] = max(clock[node], message.clock[node])
 clock["A"] += 1

# Comparing two versions:
# [A:2,B:1] vs [A:3,B:1] → second DOMINATES → it's newer
# [A:2,B:1] vs [A:1,B:2] → NEITHER dominates → concurrent → CONFLICT!

CRDTs — Auto-Merging Conflicts

Vector clocks detect conflicts; someone still has to resolve them. Conflict-free Replicated Data Types go further: they're data structures mathematically designed so that any two divergent copies always merge to the same correct result — no coordination, no conflict resolution code.

G-Counter

Grow-only counter. Each node increments only its own slot; merge = elementwise max; total = sum of slots. No conflict is even possible.

PN-Counter

Two G-Counters: one for increments, one for decrements. Value = P − N. Perfect for like counts and subscriber counts.

LWW-Register

Last-Writer-Wins register with timestamps. Simplest CRDT — but if clocks skew, the "loser" write silently disappears. Use with care.

CRDTs in the wild

Figma uses CRDT-style techniques for collaborative editing — multiple designers editing the same layer simultaneously, merging without locks. Apple Notes sync, Riak, and Azure Cosmos DB all use CRDT-based approaches. When you need multi-master writes with zero coordination, CRDTs are the principled answer.

Availability Patterns: Surviving Failure

Availability comes from one idea — redundancy — applied two ways: failover (a spare takes over) and replication (multiple copies serve at once).

Active-passive failover

One node serves traffic (active); a second waits in the wings (passive). They exchange heartbeats — periodic "still alive?" pings. If heartbeats stop, the passive node takes over the IP address or DNS name and starts serving.

Drawbacks: you pay for hardware that's idle most of its life, and there's a blip of downtime during failover. If the standby's data lags, recent writes can be lost.

Active-active failover

Both nodes serve traffic simultaneously, with a load balancer (or geo-DNS) spreading requests between them. Lose one and the other simply absorbs the load. No idle hardware — but now both nodes must handle writes or share state, which drags in the replication problems below.

Master-slave (primary-replica) replication

One primary takes all writes and streams its change log to read-only replicas. Reads scale beautifully — just add replicas. The catch is replication lag: read a replica right after writing the primary and you might not see your own write. If the primary dies, a replica must be promoted (manually or via election), and unreplicated writes can vanish.

Master-master (multi-primary) replication

Every node accepts writes and syncs with the others. Survives any single node loss with no promotion dance — but two nodes can accept conflicting writes to the same row at the same moment. Now you need conflict resolution: last-writer-wins (data loss risk), CRDTs, or app-level merging. Many teams sidestep conflicts entirely by partitioning writes (odd IDs to node 1, even to node 2).

PatternWritesFailure behaviorMain pain
Active-passiveOne nodeStandby promoted on heartbeat lossIdle spare, failover blip
Active-activeBoth nodesSurvivor absorbs trafficState sync complexity
Master-slavePrimary onlyReplica promotion neededReplication lag, lost tail writes
Master-masterAll nodesSeamlessWrite conflicts

Active-Passive vs Active-Active Deep Dive

The failover patterns above deserve a closer look, because the gap between "cold standby" and "active-active" is the gap between minutes of downtime and none:

1
Active-Passive (cold standby)

The passive server only receives heartbeats; data syncs periodically. Failover time: seconds to minutes. RPO depends on sync frequency — you lose whatever wasn't synced. Simplest and cheapest, but you pay for capacity that sits idle.

2
Active-Passive (warm standby)

The passive server mirrors the primary in real time and can take over in seconds. Near-zero RPO. More expensive — you're running two full systems but serving from one.

3
Active-Active

Both nodes handle traffic; the load balancer splits requests. If one dies, the other takes over instantly (near-zero RTO) — it was already serving. No wasted capacity.

RTO and RPO — The Disaster Recovery Axes

Two numbers define every disaster recovery plan. Agree on them with the business before the disaster:

RPO — Recovery Point Objective

How much data loss is acceptable? "If disaster strikes at 3pm, how old can our last good copy be?" RPO=0: synchronous replication, zero loss, expensive. RPO=1hr: hourly snapshots, cheap, lose up to an hour of work.

RTO — Recovery Time Objective

How long can the system be down during recovery? RTO≈0: active-active with instant failover. RTO=15min: warm standby plus some human involvement. RTO=4hr: restore from backup, significant downtime.

DR strategies on the RPO / RTO plane RPO: data loss → (none ... hours) RTO: downtime → (none ... hours) Active-active + sync replication RPO≈0, RTO≈0 — $$$$ Warm standby RPO=seconds, RTO=minutes — $$$ Cold standby + periodic sync RPO=minutes, RTO=tens of minutes — $$ Restore from backups RPO=hours, RTO=hours — $

Closer to the origin = less loss, less downtime, more money. Pick the point your business actually needs.

Availability Math: Series vs Parallel

This is the most useful arithmetic in this course. When a request must pass through services in sequence, availabilities multiply — and multiply means shrink:

# In series (request needs BOTH): availability drops
LB(99.9%) → App(99.9%) = 0.999 × 0.999 ≈ 99.8%
add DB(99.9%) = 0.999³ ≈ 99.7%

# In parallel (request needs EITHER): availability soars
two 99.9% replicas = 1 − (0.001 × 0.001) = 99.9999%

Every dependency you chain in series eats your nines; every redundant replica you add in parallel multiplies failure probabilities into oblivion. This single fact explains why architects obsess over removing synchronous dependencies and adding replicas.

The hidden series dependency

Parallel math only works if failures are independent. Two replicas in the same rack share a switch; two AZs share a region; everything shares your deploy pipeline. Correlated failures are why "five nines on paper" systems still make headlines.

SLAs, SLOs, and SLIs

Three acronyms that turn "the site should be up" into engineering:

1
SLI — Service Level Indicator

The measurement itself. "p99 latency over 5 minutes" or "fraction of 2xx responses." If you can't graph it, it's not an SLI.

2
SLO — Service Level Objective

Your internal target for the SLI: "99.95% of requests succeed each month." Miss it and pagers ring; the gap between 100% and the SLO is your error budget for risky deploys.

3
SLA — Service Level Agreement

The contractual promise to customers, with penalties (usually service credits) for breaking it. Always looser than the SLO — you promise 99.9% while targeting 99.95%, so you breach your own alarm before you breach the contract.

Archie says

Error budgets are sneaky-brilliant: if you're well within SLO, ship fast and take risks. If you've burned the budget, freeze features and fix reliability. It turns "devs vs ops" arguments into arithmetic.

Exponential Backoff with Jitter

When a dependency fails, clients retry. Done naively, retries make outages worse:

import random, time

def retry_with_backoff(operation, max_retries=5, base=1.0, cap=30.0):
 for attempt in range(max_retries):
 try:
 return operation()
 except TransientError:
 if attempt == max_retries - 1:
 raise # out of retries
 backoff = min(cap, base * 2 ** attempt) # 1, 2, 4, 8, 16…
 sleep_for = random.uniform(0, backoff) # "full jitter"
 time.sleep(sleep_for) # clients desynchronize
This is table stakes

The AWS SDK does exponential backoff with jitter by default. Any distributed system that retries needs it — AWS's own benchmarks showed full jitter cuts total work and completion time dramatically versus plain backoff.

Chaos Engineering: Break It on Purpose

You can't claim your failover works if you've never watched it fire. Chaos engineering injects failures deliberately — in production — so you discover the gaps on a calm Tuesday instead of during the real outage.

Chaos Monkey (2010)

Netflix's original: randomly kills production servers during business hours. If an engineer's service can't survive a dead instance, they find out fast.

🦍

Chaos Gorilla

Bigger stick: kills entire availability zones to prove the system survives a datacenter-scale failure.

Latency Monkey

Injects artificial latency between services — because "slow" is harder to handle than "dead," and timeouts are where bugs hide.

🧪

FIT

Netflix Failure Injection Testing: controlled, scoped chaos in production — fail specific calls for specific users and watch the blast radius.

Quick Check

A request flows through three services in sequence, each 99.9% available. Roughly how available is the whole path?

Exactly: 0.999 × 0.999 × 0.999 ≈ 0.997. Chaining services in series quietly triples your downtime — which is why architects fight to shorten synchronous call chains.

Interview Q&A

Three approaches: (1) Route all reads to the primary immediately after a write from that user — sticky routing for N seconds. (2) Track the replication position (LSN in Postgres) and route reads only to a replica that's caught up to that point. (3) Use synchronous replication for writes — the replica is guaranteed up-to-date before the write is acknowledged. Trade-offs: (1) adds load to the primary, (2) requires replica-lag tracking, (3) increases write latency.

HA means the system stays available despite failures — usually via redundancy and failover, which has some downtime window (seconds to minutes). Fault tolerance means the system continues operating without any service interruption even during a failure — much harder and more expensive (think NASA space shuttle computers with 5-way redundancy). In practice, most web systems aim for HA (99.99%), not true fault tolerance.

You're going from ~8.8 hrs/year of downtime to ~52 min: (1) Eliminate single points of failure — add redundancy to DB, LB, cache. (2) Multi-AZ deployment — spread across availability zones so a datacenter fire doesn't kill you. (3) Automated failover — manual intervention is too slow. (4) Health checks and circuit breakers — detect failures in seconds, not minutes. (5) Blue-green deployments — zero-downtime deploys. (6) Comprehensive monitoring with <1 min alert time. Each extra nine requires the previous nine plus more redundancy and better automation.

Anti-Patterns to Avoid

Single point of failure

One load balancer, one database, one DNS server. Always ask: "what happens if this dies?" — and keep asking until the answer is "nothing much."

Not testing failover

"We have a standby" means nothing if failover has never been rehearsed. Automating the test — like Netflix's Chaos Monkey — is table stakes.

Synchronous replication everywhere

Yes, it eliminates lag — but now every write waits for all replicas, and a slow replica slows your primary. Use async replication + read-your-own-writes techniques instead.

System Reliability

Reliability is the ability of a system to operate continuously without failure. It is distinct from simply "being up" — a reliable system must be correct, consistent, fault-tolerant, and available, even under adverse conditions.

What Reliability Actually Means

Four properties a reliable system must exhibit:

Correctness

The system returns the right answer, not just any answer. An incorrect but fast response is worse than a slow correct one.

Consistency

Users see a coherent view of data across requests and across nodes — not contradictory results.

Fault Tolerance

Individual component failures do not cascade into system-wide outages. The system degrades gracefully, not catastrophically.

Uptime

The fraction of time the system is reachable and serving requests within acceptable latency bounds.

MTBF and MTTR: Quantifying Reliability

1
MTBF — Mean Time Between Failures

The average duration a system operates before the next failure. A higher MTBF means failures happen less frequently. Improving MTBF means building more robust hardware, better software, and eliminating known failure modes.

2
MTTR — Mean Time To Recovery

The average time to detect a failure and restore service. A lower MTTR means you recover faster. Improving MTTR means better monitoring, automated failover, runbooks, and on-call discipline.

3
The Key Insight

Availability ≈ MTBF / (MTBF + MTTR). To reach five nines, you need failures to be rare and recovery to be fast. Most teams underinvest in MTTR — cutting recovery time from 30 minutes to 2 minutes often delivers more availability than preventing failures entirely.

SLAs vs SLOs vs SLIs: The Conceptual Frame

The SLAs/SLOs/SLIs section earlier covered the math and error budgets. Here is the why behind the three-layer model:

Why the layering matters

Without SLOs, engineers only learn about reliability problems when customers complain or contracts are breached. The SLO layer gives teams early warning and quantitative criteria for shipping vs. freezing feature work.

Availability vs Durability

These two properties are often conflated but address entirely different failure modes:

A system can be highly available but not durable (in-memory cache: fast but data evaporates on restart). It can be durable but not available (a cold backup tape: data is safe but inaccessible during an outage). Production systems need both.

Fault Tolerance vs High Availability

These terms are often used interchangeably but describe different engineering targets:

Practical take

For most systems, aim for HA (four nines is 52 minutes of downtime per year). Reserve fault-tolerance engineering for the truly catastrophic failure modes — payment processing, medical devices, flight control. Over-engineering FT into a consumer app wastes money and adds complexity without proportional user benefit.

Reliability in Distributed and Cloud-Native Systems

Cloud infrastructure is inherently unreliable — VMs are preempted, networks partition, disks fail silently. The cloud-native reliability mindset flips the assumption: instead of preventing failures, you design for failure.

Redundancy

Multiple instances across zones and regions. No single node is indispensable.

Self-Healing

Auto-scaling groups restart failed instances automatically. Health checks pull unhealthy nodes from rotation without human intervention.

Chaos Engineering

Inject failures deliberately (see the Chaos Engineering section) so you discover gaps on a calm Tuesday, not during an incident.

CAP-Aware Design

Acknowledge network partitions are inevitable and choose your consistency/availability trade-off explicitly rather than by accident.

Interview Prep

Reliability & Availability Interview Questions

Key questions on high availability, fault tolerance, reliability, and disaster recovery.

High Availability, Fault Tolerance & Failover Questions

High Availability (HA) refers to the ability of a system or component to be continuously operational and available with minimal downtime. The goal is to ensure that services are accessible and functional as much as possible, with systems designed to handle failures gracefully without significant disruption.

HA is crucial because modern systems — especially web-based applications — need to be reliable 24/7 to meet user expectations. Even short periods of downtime can lead to revenue loss, reputational damage, and customer dissatisfaction. Designing for HA means the system can withstand failures without causing prolonged service interruptions, ensuring a seamless user experience.

Active-Active: Multiple instances run in parallel sharing the workload. If one fails, others immediately take over with no service interruption. Provides better fault tolerance and load distribution but is more complex.

Active-Passive: One active node handles all traffic; passive nodes remain idle on standby until a failure occurs. Simpler to set up but may involve longer recovery times since the passive system must "take over" during failover.

When to choose: Active-Active when high fault tolerance, continuous operation, and load balancing are critical (mission-critical, high-traffic). Active-Passive when cost is a concern and the application can tolerate brief failover downtime.

Fault Tolerance is the ability of a system to continue operating even if one or more components fail. A fault-tolerant system maintains functionality and minimizes disruption through redundancy, failover mechanisms, and error detection.

Key difference from HA: High availability focuses on minimizing downtime — a server failure might trigger a failover with a brief interruption. Fault tolerance goes further by ensuring the system continues operating without any downtime at all during a failure. This requires much deeper investment — think redundant power supplies, memory mirroring, or NASA-style lock-step execution.

In practice: most web systems aim for HA (99.99%). True fault tolerance is reserved for medical devices, flight control, and financial core systems.

Graceful degradation means designing a system so that it continues to function with limited features or reduced performance when a failure occurs — rather than failing completely.

Examples:

  • A shopping website with a payment outage still lets users browse and add items to cart rather than showing a complete "site down" error.
  • A video streaming service degrades to lower resolution when bandwidth is constrained, so users can still watch.

This approach maintains user trust by avoiding complete failure and helping preserve some functionality during outages.

Load balancers distribute incoming traffic across multiple servers or service instances, preventing any single instance from becoming overloaded or becoming a single point of failure.

Contribution to HA:

  • Fault Tolerance: If one server fails, the load balancer automatically redirects traffic to healthy servers — zero downtime for the user.
  • Scalability: Instances can be added or removed based on traffic, keeping the system responsive under varying load.
  • Traffic Distribution: Ensures no single component becomes a bottleneck, reducing the probability of failure from overloading.

Failover is the process by which a system automatically shifts to a backup system or component when the primary system fails. This ensures continuity of service during failures without requiring manual intervention.

How it helps:

  • Minimizes Downtime: The system quickly switches to a secondary server, database, or resource without causing significant downtime.
  • Improves Fault Tolerance: Ensures systems continue running even when components become unavailable.
  • Example: In a web application, if the primary server goes down, a failover system immediately shifts traffic to a secondary server, allowing the service to continue without interruption.

Health Monitoring continuously checks the status of system components (servers, databases, services) to ensure they are functioning correctly. If a failure is detected, the system triggers recovery actions or alerts.

Self-Healing Systems automatically detect issues and take corrective actions without human intervention — restarting failed services, replacing unhealthy nodes, or scaling resources dynamically.

How they help:

  • Proactive Fault Detection: Detect and address issues before they lead to significant failures.
  • Automated Recovery: Reduces downtime by eliminating manual intervention lag.
  • Example: AWS uses health checks to ensure EC2 instances are operational. If an instance fails, the system automatically replaces it with a new one, maintaining service availability.

System Reliability Questions

System reliability is the ability of a system to consistently perform its intended function without failure over a specified period. In system design, reliability ensures:

  • Minimal downtime
  • Consistent user experience
  • Protection of data and transactions
  • Trust in the system's behavior under stress or failure

High reliability is especially critical in distributed systems, mission-critical applications (banking, healthcare), and cloud-native environments where failure can cascade across services.

Availability means the system is accessible and operational when needed. Example: a website being online 24/7 with minimal downtime.

Durability refers to the ability to retain and preserve data without loss. Example: data written to AWS S3 is not lost even if a node fails.

Analogy: Think of availability as whether the ATM is working, and durability as whether your money is still in your account. You can have one without the other — an in-memory cache is fast and available but not durable; a cold backup tape is durable but not available during an outage.

MTBF (Mean Time Between Failures): Average time between two consecutive failures. Measures how reliable a system is — higher is better.

MTTR (Mean Time To Recovery): Average time to restore service after a failure. Measures resilience and repair efficiency — lower is better.

Relationship: Availability ≈ MTBF / (MTBF + MTTR). To maximize availability, you need failures to be rare (high MTBF) and recovery to be fast (low MTTR). Most teams underinvest in MTTR — cutting recovery time from 30 minutes to 2 minutes often improves availability more than preventing additional failures.

SLAs (Service Level Agreements) are formal contracts between service providers and customers that define:

  • Expected uptime/availability (e.g., 99.9% uptime)
  • MTTR and support response times
  • Penalties for failure to meet guarantees (typically service credits)

SLAs create clear reliability goals, help prioritize engineering efforts, and hold teams accountable for reliability metrics. They also drive the SLO/SLI layering — the internal SLO target is always stricter than the SLA so that internal alarms fire before a customer contract is breached.

To achieve 99.99% ("four nines" — ~52 minutes of downtime per year):

  • Redundancy: Multiple instances across availability zones and regions — no single node is indispensable.
  • Load balancing and failover: Health checks pull failed instances from rotation automatically.
  • Graceful degradation: Non-critical features shed load before core functionality degrades.
  • Auto-healing: Auto-scaling groups restart or replace failed instances without manual intervention.
  • Distributed storage: Multi-AZ databases (e.g., RDS Multi-AZ) with automated failover.
  • Chaos engineering: Continuously test failure scenarios so you discover gaps before they become incidents.

Example: Multi-AZ setup in AWS with auto-scaling groups, health checks, circuit breakers, and retry-with-backoff at the application layer.

Systematic approach:

  • Step 1: Check monitoring and alert logs for patterns — memory leaks, CPU spikes, OOM kills, GC pauses.
  • Step 2: Analyze failure rate vs. expected MTBF to understand if failures are increasing in frequency.
  • Step 3: Review recent code deployments and infrastructure changes — correlate with failure timestamps.
  • Step 4: Add circuit breakers, retries with backoff, or bulkheads to improve resilience against downstream dependencies.
  • Step 5: Add observability (distributed tracing, structured logging) to understand root cause at the request level.

Use SRE practices like blameless postmortems to identify systemic issues and prevent recurrence.

  • Scale horizontally using stateless services so any instance can serve any request.
  • Partition/shard databases to distribute data volume and query load.
  • Use message queues (e.g., Kafka) to decouple services and absorb traffic spikes without cascading failures.
  • Implement caching (e.g., Redis) to reduce repeated load on databases.
  • Apply rate limiting and throttling to protect downstream services from being overwhelmed.
  • Optimize MTTR with autoscaling groups and self-healing infrastructure.

Example stack: Kafka for event ingestion, Redis for caching, PostgreSQL read replicas for query load distribution.

  • Deploy services in multiple availability zones or regions to tolerate data center failures.
  • Use health checks with load balancers to reroute traffic away from unhealthy instances automatically.
  • Leverage managed services (e.g., RDS Multi-AZ, DynamoDB global tables) that handle replication and failover internally.
  • Automate failover using DNS-based routing tools like AWS Route 53 (geo DNS) or Azure Traffic Manager.
  • Maintain replication and backup recovery plans tested regularly via DR drills.

Redundancy prevents single points of failure; failover ensures continuity when failures inevitably occur.

Sample answer: "On a real-time analytics dashboard, we initially fetched live data directly from the primary database to ensure up-to-the-second accuracy. However, this increased query load significantly and degraded reliability during traffic spikes. We chose to introduce a 15-second cache layer, accepting a slight staleness in the dashboard to greatly improve system stability and reduce MTTR during peak hours."

Framework for answering: Identify the trade-off explicitly (latency vs. consistency, throughput vs. durability), describe how you quantified the cost of each option, state what drove the decision (user impact, SLO budget, business priority), and explain how you monitored the outcome.

  • Start with SLAs to define clear, bounded reliability goals — don't design for five nines when three nines meets the requirement.
  • Apply the Pareto Principle: find the 20% of failure modes causing 80% of downtime and fix those first.
  • Incremental improvement: monitor → analyze → fix one thing at a time rather than adding speculative infrastructure.
  • Avoid unnecessary complexity: each extra layer (service mesh, sidecar, distributed cache) is a new failure mode — add only when the reliability benefit is measurable.
  • Prefer managed cloud services where possible — let AWS/GCP handle the operational complexity of replication, backups, and failover.

Focus on simplicity, observability, and resilience over theoretical perfection.

Disaster Recovery Questions

Backup is the process of copying and storing data to protect against loss or corruption. Backups let you restore data to a previous state but do not ensure service availability during an outage — restoring from backup takes time.

Failover is automatic switching to a redundant or standby system when the primary fails. It keeps services running with minimal downtime but does not help if data has been corrupted or deleted.

Key distinction: Backups are for data recovery; failover is for service continuity. Best practice: use both — backups to restore lost or corrupted data, failover to keep systems live during infrastructure failures.

Step-by-step:

  • Start with business requirements: Define RTO (Recovery Time Objective) and RPO (Recovery Point Objective) — these constrain every downstream decision.
  • Multi-region deployment: Deploy application servers and databases in active-active or active-passive mode across regions. Replicate data asynchronously or synchronously based on RPO requirements.
  • Implement failover: DNS-based failover (e.g., AWS Route 53, GCP Global LB) with health checks to detect failure and trigger routing changes automatically.
  • Add data backups: Frequent snapshots, object versioning, and offsite storage to recover from data corruption or accidental deletion.
  • Automate recovery: Runbooks and infrastructure-as-code so recovery is repeatable and fast.
  • Perform DR drills: Regularly test the full recovery plan — an untested DR plan is not a DR plan.

RTO (Recovery Time Objective): The maximum acceptable time to restore service after a failure. If your RTO is 1 hour, the system must be serving traffic again within 60 minutes of an outage.

RPO (Recovery Point Objective): The maximum acceptable amount of data loss measured in time. If your RPO is 5 minutes, you cannot lose more than 5 minutes of writes.

How to optimize:

  • Lower RTO: Automated failover, container orchestration (Kubernetes can reschedule pods in seconds), hot standby environments that are always ready to serve.
  • Lower RPO: Real-time or near-real-time data replication — log shipping, change data capture (CDC), synchronous multi-region writes.
  • Cost trade-off: Shorter RTO/RPO means higher infrastructure and operational cost. The goal is to meet business requirements, not to minimize both to zero.
  • Data consistency: Keeping data in sync across regions is difficult, especially under network partition. Replication lag means the standby region may be behind the primary.
  • Latency: Cross-region replication introduces delays — synchronous replication across continents adds significant write latency.
  • Split-brain scenarios: Without proper coordination, different regions may each believe they are the primary, causing conflicting writes and data divergence.
  • Data locality & compliance: Regulations like GDPR may restrict storing user data in certain regions, constraining where failover targets can be located.
  • Failover orchestration complexity: Switching traffic, promoting standby databases, syncing in-flight transactions, and updating DNS all must happen in the right order during high-stress incidents.

Quorum-based design ensures that decisions — leader election, write confirmation, configuration changes — require agreement from a majority of nodes, preventing inconsistency or split-brain during failover.

Example: In a 5-node cluster, at least 3 nodes must agree (quorum = ⌊N/2⌋ + 1) before committing a write or electing a new leader. If 2 nodes are partitioned off, the remaining 3 still form a quorum and can proceed safely.

Used in:

  • Consensus protocols: Paxos, Raft
  • Systems: etcd, ZooKeeper, CockroachDB

Quorum ensures safe recovery and continued availability even during regional failures, at the cost of requiring a majority of nodes to be reachable for writes to proceed.

Further Reading

Try It

Interactive: Consistency Model Visualiser

Write a value to the primary, then immediately read from a replica. See how Strong, Eventual, and Read-Your-Writes consistency models behave differently under replication lag.