Command Palette

Search for a command to run...

Hectal

Guide G1 · DevOps path

Production Architecture, High Availability, and Disaster Recovery

How a production request flows from DNS to database and back, designing for high availability (no single point of failure, multi-AZ), multi-region patterns, the four disaster recovery strategies, and how observability and on-call close the loop.

Advanced 55 min

Start here

The mental model

Every course so far built one layer. This guide stacks them into one picture and asks one question at every layer: 'what happens when THIS dies?'. A production architecture is one where the answer is always 'something else takes over, and someone is told'.

HIGH AVAILABILITY keeps the service running through everyday failures (a server, a disk, an availability zone) with redundancy and automatic failover. DISASTER RECOVERY is the plan for the rare, big failures (a region outage, data corruption, a deleted account) where you restore from elsewhere. HA is measured in uptime; DR in RPO and RTO (Stateful Systems course, Unit 0.3).

Go deeper

How it works inside

01One request, end to end

A user opens shoplite.dev. ROUTE 53 resolves the name, possibly choosing a region by latency or health (Networking course, DNS). CLOUDFRONT serves static assets from an edge location near the user and forwards API calls. AWS WAF filters abusive traffic at the edge; Shield absorbs network-level floods. An ALB (or the Gateway API load balancer, Platform course) in the region spreads requests across pods in several AZs. EKS runs the stateless API and workers; they read from REDIS (cache), write to POSTGRESQL (the system of record), and publish events to KAFKA for asynchronous work (Stateful Systems course). Every hop emits metrics, logs, and traces that feed Prometheus, Loki, and Tempo, visualised in Grafana; ALERTMANAGER pages the ON-CALL engineer, who follows a RUNBOOK (SRE course).

One request, end to enddiagram
Rendering diagram…

02High availability: remove single points of failure

Go layer by layer and look for anything that exists ONCE: one NAT gateway (AWS course, routing), one database instance, one Kafka broker holding a partition, one replica of a service, one person who knows how to deploy. For each, add redundancy across failure domains (at least two AZs, usually three), health checks, and automatic failover.

Availability multiplies: if a request depends on 5 components that are each 99.9% available, the chain is at most ~99.5%. Redundancy helps in parallel (two independent 99% replicas give ~99.99%), and DEPENDENCIES hurt in series. So remove hard dependencies too: time out and degrade gracefully (show products without recommendations) instead of failing the whole page (SRE course, cascading failures).

03Multi-region

Multi-AZ protects against a data-centre failure and is the right default. Multi-REGION protects against a regional outage or a regional control-plane problem, at a big cost in complexity: data must be replicated across regions (Aurora Global Database, DynamoDB global tables, S3 replication, Kafka MirrorMaker), and writes in two places raise consistency questions (Stateful Systems course, Unit 0.1).

ACTIVE-PASSIVE: one region serves traffic; the other holds replicated data and (scaled-down) infrastructure, and Route 53 failover routing switches on health-check failure. ACTIVE-ACTIVE: both regions serve users (latency-based routing), which needs data designed for multi-region writes or partitioned by user. Most companies should master multi-AZ and a tested DR plan before going active-active.

04The four DR strategies

From cheapest/slowest to most expensive/fastest (the AWS Well-Architected reliability pillar uses the same names): BACKUP AND RESTORE (backups copied to another region; rebuild everything with Terraform and GitOps on disaster, RTO in hours). PILOT LIGHT (data continuously replicated; core infrastructure exists but is switched off or minimal; scale up on disaster, RTO in tens of minutes). WARM STANDBY (a scaled-down but fully running copy; scale out and switch DNS, RTO in minutes). MULTI-SITE ACTIVE-ACTIVE (full capacity in both; RTO near zero).

Everything as code is what makes DR affordable: if the whole platform can be rebuilt from Terraform plus GitOps (GitOps course, Mission 2.4), 'backup and restore' covers most businesses. The part that can't be rebuilt from code is DATA, so that's where replication and tested backups matter.

Do it

Hands-on lab

  1. 1

    Find the single points of failure

    Fill this table for ShopLite's current architecture. Every 'Count = 1' row is a work item.

    spof-review.mdwhole filemarkdown
    | Component        | Count | Failure domain | If it dies...                 | Fix                                   |
    |------------------|-------|----------------|-------------------------------|---------------------------------------|
    | NAT gateway      | 1     | ap-south-1a    | private subnets lose internet | one NAT per AZ                        |
    | RDS PostgreSQL   | 1     | ap-south-1a    | total outage                  | Multi-AZ; tested PITR                 |
    | Redis            | 1     | node           | cache cold, DB overload       | replica + Sentinel / ElastiCache MAZ  |
    | checkout pods    | 2     | same node!     | outage on node drain          | topologySpreadConstraints + PDB       |
    | Argo CD          | 1     | cluster        | deploys stop (apps keep running) | HA install; DR = reinstall + root app |
    | Deploy knowledge | 1     | Ravi           | nobody can release            | runbooks, pipelines, pairing          |
  2. 2

    Spread pods across zones

    Replicas on the same node or zone aren't redundancy. Topology spread constraints (Kubernetes course, affinity) force the scheduler to spread them.

    apps/checkout/base/deployment.yamladd to fileyaml
        spec:
          topologySpreadConstraints:
            - maxSkew: 1
              topologyKey: topology.kubernetes.io/zone
              whenUnsatisfiable: DoNotSchedule
              labelSelector: { matchLabels: { app: checkout } }
            - maxSkew: 1
              topologyKey: kubernetes.io/hostname
              whenUnsatisfiable: ScheduleAnyway
              labelSelector: { matchLabels: { app: checkout } }
  3. 3

    DNS failover between regions (Terraform)

    Route 53 health-checks the primary region's endpoint; when it fails, answers switch to the secondary. Keep the TTL short (60 s) so clients follow quickly. This is the switch for active-passive and warm-standby designs.

    envs/global/dns.tfwhole filehcl
    resource "aws_route53_health_check" "primary" {
      fqdn              = "api-mumbai.shoplite.dev"
      type              = "HTTPS"
      resource_path     = "/healthz"
      failure_threshold = 3
      request_interval  = 10
    }
    
    resource "aws_route53_record" "api_primary" {
      zone_id         = var.zone_id
      name            = "api.shoplite.dev"
      type            = "CNAME"
      ttl             = 60
      records         = ["api-mumbai.shoplite.dev"]
      set_identifier  = "primary"
      health_check_id = aws_route53_health_check.primary.id
      failover_routing_policy { type = "PRIMARY" }
    }
    
    resource "aws_route53_record" "api_secondary" {
      zone_id        = var.zone_id
      name           = "api.shoplite.dev"
      type           = "CNAME"
      ttl            = 60
      records        = ["api-singapore.shoplite.dev"]
      set_identifier = "secondary"
      failover_routing_policy { type = "SECONDARY" }
    }
  4. 4

    Write the DR runbook, then run it

    A DR plan is a runbook with owners, commands, and a measured time, rehearsed at least twice a year (SRE course, game days). The first rehearsal always finds missing steps.

    runbooks/dr-region-failover.mdwhole filemarkdown
    # DR: fail over ShopLite from ap-south-1 to ap-southeast-1 (warm standby)
    
    Owner: platform on-call · Target RTO: 30 min · Target RPO: 5 min · Last rehearsal: 2026-08-14 (took 41 min)
    
    1. Declare the incident; incident commander assigned (SRE course, incident command).
    2. Freeze deploys: pause Argo CD auto-sync for prod-mumbai.
    3. Promote the Aurora Global Database secondary in ap-southeast-1 (managed failover) and confirm writes.
    4. Scale prod-singapore: `kubectl --context prod-sg scale deploy --all --replicas=...` / Karpenter limits up.
    5. Point secrets/config at the new DB endpoint (External Secrets refresh).
    6. Route 53: fail over api.shoplite.dev (automatic via health check; force if needed).
    7. Verify: synthetic checkout succeeds; error rate and latency SLOs green.
    8. Communicate status; plan fail-back after the region recovers.

Operate it

Knobs that matter

SettingDefaultWhat it doesWhen to change it
Route 53 record TTL300s typicalHow long resolvers cache answers.60s on failover records so clients switch quickly; not lower than needed (more queries).
Health check failure_threshold × interval3 × 30sTime to detect a dead endpoint.3 × 10s for faster failover; balance against false positives.
topologySpreadConstraintsnoneHow pods spread across zones/nodes.Zone DoNotSchedule for critical services; host ScheduleAnyway.
RPO / RTO targetsundefined (the real default!)Allowed data loss / downtime.Agree them with the business per service; they choose the DR strategy and its cost.

3am practice

Failure drills

Each drill is a real failure mode. Read the scenario and the output, decide what's wrong, then reveal the diagnosis.

Drill #1

Multi-AZ, but everything died with one zone

ap-south-1a has a power event. ShopLite runs 'across three AZs', yet the whole site is down for 40 minutes.

terminal
$ aws ec2 describe-nat-gateways --query 'NatGateways[].{id:NatGatewayId,subnet:SubnetId,state:State}' --output table
── what you'll see ──
-------------------------------------------------------
| DescribeNatGateways |
+-------------------------+------------------+--------+
| id | subnet | state |
+-------------------------+------------------+--------+
| nat-0a1b2c3d4e5f60718 | subnet-az-a-pub | available |
+-------------------------+------------------+--------+

Drill #2

The DR region that couldn't start

During a DR rehearsal, the standby region's services fail to start.

terminal
$ kubectl --context prod-sg -n checkout get pods
── what you'll see ──
NAME READY STATUS RESTARTS
checkout-7d9c6b5f4-x2k8p 0/1 ImagePullBackOff 0
# Failed to pull image "123456789012.dkr.ecr.ap-south-1.amazonaws.com/checkout:sha-3f2a1c9": dial tcp: i/o timeout

Decide

Disaster recovery strategies

StrategyTypical RPOTypical RTOCostWhat runs in the DR region
Backup & restoreHours (last backup)Hours$Nothing; backups + IaC to rebuild
Pilot lightMinutes (replication)10s of minutes$$Replicated data; core infra off or minimal
Warm standbySeconds–minutesMinutes$$$Scaled-down full stack, ready to scale
Multi-site active-activeNear zeroNear zero$$$$Full stack serving live traffic

The bigger picture

Connects to

Prove it

Interview questions

01

Walk through what happens when a user hits your production URL.

02

HA vs DR?

03

Describe the DR strategies and how you'd choose.