Skip to content

Multi-Region Infrastructure Overview

Why Multi-Region Exists

On February 28, 2017, a single mistyped command during routine maintenance in AWS's US-East-1 region took down S3 — and with it, a significant portion of the internet. Companies that relied exclusively on US-East-1 lost revenue, customers, and trust. Companies that had multi-region architectures barely noticed.

Multi-region infrastructure distributes your application across multiple geographic locations — not just for performance, but for survival. It addresses three fundamental requirements that single-region architectures cannot satisfy:

  1. Blast radius containment: A failure in one region should not take down the entire application
  2. Latency optimization: Users in Tokyo shouldn't wait 200ms for data to round-trip to Virginia
  3. Regulatory compliance: GDPR, data residency laws, and sovereignty requirements demand data stays in specific geographies

The Problem at Scale

ProblemSingle RegionMulti-Region
Region outageTotal downtimeAutomatic failover
User latency (global)100-300ms for distant users< 50ms for all users
Data residencySingle jurisdictionComply with local laws
Disaster recoveryRPO/RTO in hoursRPO/RTO in minutes/seconds
Peak capacityLimited by one region's capacityGlobal capacity pool
Blast radiusEverything at riskIsolated failure domains

Historical Context

EraApproachLimitations
2000sPrimary + warm standby datacenterManual failover, hours of downtime
2010sActive-passive across regionsData lag, complex failover
2015sActive-active with eventual consistencySplit-brain risk, complex data management
2020sCell-based architectureEngineering complexity, but near-zero downtime
2025+Edge-native, globally distributed databasesReduced latency, but cost challenges

First Principles

The CAP Theorem in Multi-Region

The CAP theorem states that a distributed system can provide at most two of three guarantees: Consistency, Availability, and Partition tolerance. In multi-region deployments, network partitions between regions will happen — they are not theoretical, they are operational reality.

CAP: Choose two of {C,A,P}

Since partition tolerance is mandatory across regions (you cannot guarantee zero network issues between Virginia and Tokyo), the real choice is:

Multi-Region: C+P (sacrifice availability)orA+P (sacrifice consistency)

In practice, most multi-region systems choose AP — availability and partition tolerance — accepting eventual consistency. Critical operations (payments, identity) may use CP — consistency and partition tolerance — accepting brief unavailability during network partitions.

Latency Physics

The speed of light in fiber optic cable is approximately 2×108 m/s (about 2/3 the speed of light in vacuum). This creates hard physical limits on cross-region latency:

Tone-way=dcfiber=d2×108 m/sTround-trip=2×Tone-way+Tprocessing+Trouting
RouteDistance (km)Theoretical Min RTTTypical RTT
US-East <-> US-West3,90039 ms60-80 ms
US-East <-> EU-West5,60056 ms80-100 ms
US-East <-> AP-Tokyo10,800108 ms150-200 ms
EU-West <-> AP-Tokyo9,40094 ms120-160 ms
US-East <-> AP-Sydney15,900159 ms200-250 ms
EU-West <-> AP-Sydney17,000170 ms220-280 ms

These are physical constraints — no amount of engineering can make light travel faster. Multi-region architecture works with physics, not against it, by placing compute and data closer to users.

The Availability Equation

Single-region availability is bounded by the region's SLA. Multi-region availability is the complement of simultaneous failure:

Asingle=AregionAmulti=1i=1n(1Ai)

For two regions each with 99.99% availability:

Amulti=1(10.9999)2=10.00000001=99.999999%

In practice, this theoretical availability is reduced by:

  • Failover detection time
  • DNS propagation delay
  • Data replication lag
  • Shared dependencies (global control plane, shared DNS)

A more realistic model:

Aeffective=Amulti×(1Pcorrelated)×(1Pfailover_failure)

Where Pcorrelated is the probability of correlated failures and Pfailover_failure is the probability that the failover mechanism itself fails.

Core Mechanics

Architecture Patterns Overview

PatternRPORTOCost MultiplierComplexity
Active-PassiveMinutesMinutes-Hours1.3-1.5xLow
Active-ActiveSecondsSeconds2.0-2.5xHigh
Cell-BasedZero (per cell)Seconds2.0-3.0xVery High

These are covered in depth in Architecture Patterns.

The Data Problem

Data is the hardest part of multi-region. Compute is stateless — spin up containers anywhere. But data has gravity:

Data replication strategies (covered in Data Replication):

StrategyConsistencyLatency ImpactConflict Risk
Synchronous replicationStrongHigh (adds cross-region RTT)None
Asynchronous replicationEventualNonePossible
Semi-synchronousBounded stalenessModerateLow
CRDT-basedEventual (convergent)NoneAuto-resolved

Traffic Management

Routing users to the right region requires multiple layers of traffic management:

Detailed in Traffic Routing.

Implementation: Multi-Region Infrastructure with Terraform

hcl
# infrastructure/main.tf — Multi-region setup
terraform {
  required_version = ">= 1.5"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  backend "s3" {
    bucket         = "myorg-terraform-state"
    key            = "multi-region/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

# Primary region
provider "aws" {
  region = "us-east-1"
  alias  = "primary"
}

# Secondary region
provider "aws" {
  region = "eu-west-1"
  alias  = "secondary"
}

# Tertiary region
provider "aws" {
  region = "ap-northeast-1"
  alias  = "tertiary"
}

locals {
  regions = {
    primary = {
      region     = "us-east-1"
      cidr       = "10.0.0.0/16"
      is_primary = true
    }
    secondary = {
      region     = "eu-west-1"
      cidr       = "10.1.0.0/16"
      is_primary = false
    }
    tertiary = {
      region     = "ap-northeast-1"
      cidr       = "10.2.0.0/16"
      is_primary = false
    }
  }
}

# VPC per region
module "vpc_primary" {
  source    = "./modules/vpc"
  providers = { aws = aws.primary }

  region = local.regions.primary.region
  cidr   = local.regions.primary.cidr
  name   = "primary"
}

module "vpc_secondary" {
  source    = "./modules/vpc"
  providers = { aws = aws.secondary }

  region = local.regions.secondary.region
  cidr   = local.regions.secondary.cidr
  name   = "secondary"
}

module "vpc_tertiary" {
  source    = "./modules/vpc"
  providers = { aws = aws.tertiary }

  region = local.regions.tertiary.region
  cidr   = local.regions.tertiary.cidr
  name   = "tertiary"
}

# Cross-region VPC peering
resource "aws_vpc_peering_connection" "primary_to_secondary" {
  provider    = aws.primary
  vpc_id      = module.vpc_primary.vpc_id
  peer_vpc_id = module.vpc_secondary.vpc_id
  peer_region = "eu-west-1"
  auto_accept = false

  tags = {
    Name = "primary-to-secondary"
  }
}

resource "aws_vpc_peering_connection_accepter" "secondary_accept" {
  provider                  = aws.secondary
  vpc_peering_connection_id = aws_vpc_peering_connection.primary_to_secondary.id
  auto_accept               = true
}

# Global Accelerator for traffic routing
resource "aws_globalaccelerator_accelerator" "main" {
  provider        = aws.primary
  name            = "myapp-global"
  ip_address_type = "IPV4"
  enabled         = true

  attributes {
    flow_logs_enabled   = true
    flow_logs_s3_bucket = "myorg-flow-logs"
    flow_logs_s3_prefix = "global-accelerator/"
  }
}

resource "aws_globalaccelerator_listener" "https" {
  provider        = aws.primary
  accelerator_arn = aws_globalaccelerator_accelerator.main.id
  protocol        = "TCP"

  port_range {
    from_port = 443
    to_port   = 443
  }
}

resource "aws_globalaccelerator_endpoint_group" "primary" {
  provider                  = aws.primary
  listener_arn              = aws_globalaccelerator_listener.https.id
  endpoint_group_region     = "us-east-1"
  health_check_port         = 443
  health_check_protocol     = "TCP"
  health_check_interval_seconds = 10
  threshold_count           = 3
  traffic_dial_percentage   = 100

  endpoint_configuration {
    endpoint_id = module.alb_primary.arn
    weight      = 100
  }
}

resource "aws_globalaccelerator_endpoint_group" "secondary" {
  provider                  = aws.secondary
  listener_arn              = aws_globalaccelerator_listener.https.id
  endpoint_group_region     = "eu-west-1"
  health_check_port         = 443
  health_check_protocol     = "TCP"
  health_check_interval_seconds = 10
  threshold_count           = 3
  traffic_dial_percentage   = 100

  endpoint_configuration {
    endpoint_id = module.alb_secondary.arn
    weight      = 100
  }
}

Application-Level Region Awareness

typescript
// src/region/region-config.ts
interface RegionConfig {
  regionId: string;
  isPrimary: boolean;
  endpoints: {
    database: string;
    cache: string;
    queue: string;
    storage: string;
  };
  failover: {
    targetRegion: string;
    healthCheckUrl: string;
    failoverThreshold: number;
  };
  dataResidency: {
    allowedRegions: string[];
    piiStorage: 'local' | 'primary';
  };
}

const REGION_CONFIGS: Record<string, RegionConfig> = {
  'us-east-1': {
    regionId: 'us-east-1',
    isPrimary: true,
    endpoints: {
      database: 'primary-db.us-east-1.rds.amazonaws.com',
      cache: 'primary-cache.us-east-1.cache.amazonaws.com',
      queue: 'https://sqs.us-east-1.amazonaws.com/123456789/main-queue',
      storage: 'myapp-data-us-east-1',
    },
    failover: {
      targetRegion: 'eu-west-1',
      healthCheckUrl: 'https://api.eu-west-1.myapp.com/health',
      failoverThreshold: 3,
    },
    dataResidency: {
      allowedRegions: ['us-east-1', 'us-west-2'],
      piiStorage: 'local',
    },
  },
  'eu-west-1': {
    regionId: 'eu-west-1',
    isPrimary: false,
    endpoints: {
      database: 'secondary-db.eu-west-1.rds.amazonaws.com',
      cache: 'secondary-cache.eu-west-1.cache.amazonaws.com',
      queue: 'https://sqs.eu-west-1.amazonaws.com/123456789/main-queue',
      storage: 'myapp-data-eu-west-1',
    },
    failover: {
      targetRegion: 'us-east-1',
      healthCheckUrl: 'https://api.us-east-1.myapp.com/health',
      failoverThreshold: 3,
    },
    dataResidency: {
      allowedRegions: ['eu-west-1', 'eu-central-1'],
      piiStorage: 'local',
    },
  },
};

class RegionManager {
  private config: RegionConfig;
  private healthChecker: HealthChecker;

  constructor(regionId: string) {
    this.config = REGION_CONFIGS[regionId];
    if (!this.config) {
      throw new Error(`Unknown region: ${regionId}`);
    }
    this.healthChecker = new HealthChecker(this.config.failover);
  }

  get isPrimary(): boolean {
    return this.config.isPrimary;
  }

  getEndpoint(service: keyof RegionConfig['endpoints']): string {
    return this.config.endpoints[service];
  }

  canStoreData(dataType: 'pii' | 'general'): boolean {
    if (dataType === 'pii') {
      return this.config.dataResidency.piiStorage === 'local';
    }
    return true;
  }

  async shouldFailover(): Promise<boolean> {
    return this.healthChecker.isUnhealthy();
  }
}

Edge Cases & Failure Modes

Multi-Region Failure Scenarios

Failure ModeDescriptionMitigation
Split brainBoth regions think they're primaryLeader election with distributed consensus
Replication lag during failoverSecondary behind by minutesAccept data loss or wait for sync
DNS propagation delayUsers still hitting failed regionLow TTL + client-side retry
Thundering herd on failoverAll traffic hits secondary at onceRate limiting, auto-scaling warm pools
Correlated failuresBoth regions in same blast radiusUse truly independent failure domains
Data divergenceConflicting writes in active-activeCRDTs, last-writer-wins, or conflict resolution
Certificate/DNS issuesGlobal resources that span regionsRedundant certificate providers
Cascading failuresFailed region overloads surviving regionCircuit breakers, load shedding

The Split-Brain Problem

Performance Characteristics

Multi-Region Latency Budget

Ttotal=TDNS+TTLS+Tnetwork+Tprocessing+Tdata
ComponentLocal RegionCross-Region
DNS resolution1-5 ms1-5 ms
TLS handshake5-20 ms50-100 ms
Network RTT1-5 ms50-200 ms
Application processing10-50 ms10-50 ms
Database query5-20 ms60-250 ms (if cross-region)
Total22-100 ms171-605 ms

Cost Comparison

ComponentSingle Region2 Regions3 Regions
Compute$10,000/mo$18,000/mo$26,000/mo
Database$5,000/mo$9,000/mo$13,000/mo
Data transfer$500/mo$3,000/mo$7,000/mo
Load balancing$200/mo$600/mo$1,000/mo
DNS + health checks$50/mo$150/mo$250/mo
Total$15,750/mo$30,750/mo$47,250/mo
Cost multiplier1.0x1.95x3.0x

Detailed in Cost Analysis.

Mathematical Foundations

Replication Lag Model

For asynchronous replication between regions:

L=W×SBW×S

Where:

  • L = replication lag (seconds)
  • W = write rate (writes/second)
  • S = average write size (bytes)
  • B = replication bandwidth (bytes/second)

When W×S approaches B, lag grows unbounded — the replica can never catch up.

Quorum Systems

For a replicated system with n replicas, read quorum r and write quorum w:

r+w>n(for strong consistency)w>n2(to prevent conflicting writes)

With 3 regions: r=2,w=2 provides strong consistency. With 5 regions: r=3,w=3 provides strong consistency with tolerance for 2 region failures.

Real-World War Stories

War Story — The US-East-1 Dependency

In 2017, an S3 outage in US-East-1 cascaded across the internet because many "multi-region" applications had hidden dependencies on US-East-1. AWS's own service health dashboard was hosted in US-East-1 and went down, making it impossible to even check the status of the outage.

Hidden dependencies that broke "multi-region" apps:

  • S3 buckets for static assets (only in US-East-1)
  • IAM/STS endpoints (global service with US-East-1 dependency)
  • CloudFront origin in US-East-1
  • Route 53 health checks configured in US-East-1
  • Terraform state stored in US-East-1 S3

Lesson: Multi-region means multi-region for EVERYTHING — not just compute. Audit every dependency, every service, every configuration for region-specific assumptions.

War Story — The $2M Replication Bill

A social media startup launched active-active in 3 regions. Their real-time feed system replicated every post, comment, and reaction to all regions. With 500 million events/day at 2 KB average, cross-region data transfer hit 1 TB/day. At $0.02/GB for inter-region transfer, their monthly bill for data transfer alone was $600/month... until they went viral and traffic grew 100x. The data transfer bill hit $60,000/month. Combined with triple compute costs, their multi-region infrastructure cost more than their revenue.

Fix: Moved to cell-based architecture. User data lives in the user's home region. Global data (trending topics) uses a lightweight CRDT that transfers only delta updates (100x less data). Cross-region transfer dropped from 1 TB/day to 10 GB/day.

Lesson: Multi-region data transfer costs grow linearly with traffic. Design your data model to minimize cross-region replication from the start.

Decision Framework

Do You Actually Need Multi-Region?

Choosing Your Architecture

FactorActive-PassiveActive-ActiveCell-Based
Implementation effortLowHighVery High
Operational complexityLowHighVery High
Cost multiplier1.3-1.5x2.0-2.5x2.0-3.0x
RPOMinutesSecondsZero
RTOMinutesSecondsSeconds
Data consistencyStrongEventualStrong (per cell)
Best forDR onlyGlobal latencyMassive scale

Section Overview

This section covers multi-region infrastructure in depth:

PageWhat You'll Learn
Architecture PatternsActive-passive, active-active, cell-based architectures
Data ReplicationCross-region replication, conflict resolution, CRDTs
Traffic RoutingGeoDNS, latency-based routing, Global Accelerator
Failover StrategiesDNS failover, RPO/RTO analysis, automated failover
Cost AnalysisData transfer costs, compute duplication, optimization

Start with Architecture Patterns to understand the fundamental approaches, then dive into Data Replication for the hardest engineering challenge in multi-region systems.

Advanced Topics

The Edge Computing Continuum

Multi-region is evolving toward edge computing — pushing compute and data to dozens or hundreds of locations:

Edge platforms like Cloudflare Workers, Fly.io, and Deno Deploy run application code in 200+ locations worldwide, achieving < 10ms latency for most users. However, they face the same fundamental data challenge: compute can be everywhere, but data can't.

Globally Distributed Databases

A new generation of databases is designed for multi-region from the ground up:

DatabaseConsistency ModelReplicationLatencyCost
CockroachDBSerializableSynchronous (Raft)Higher (consensus overhead)$$$
Google SpannerLinearizableSynchronous (TrueTime)Higher (GPS clocks)$$$$
YugabyteDBTunableSynchronous (Raft)Tunable$$$
PlanetScale (Vitess)EventualAsynchronousLow$$
DynamoDB Global TablesEventualAsynchronous (last-writer-wins)Low$$
CassandraDBTunableConfigurable quorumTunable$$

The choice between these depends on your consistency requirements, latency budget, and willingness to pay — covered in Data Replication.

"What I cannot create, I do not understand." — Richard Feynman