Skip to content
chiltepin

Generated from: “Show how the service is laid out across regions and availability zones, with how many copies of each part run.

Orders service — regions, zones, and replicas

Written by an agent from the skill, validated by chiltepin check, rendered by the renderer — shown as generated, 13 September 2026.

DOCUMENTDRAFT

Orders service — regions, zones, and replicas

Where each part of the Orders service runs, and how many copies of it exist.

The Orders service runs in two regions. us-east-1 takes all writes and most reads; eu-west-1 serves European reads and takes over writes only on a declared failover. Each region spreads its parts across three availability zones. The loss of one zone removes at most a third of the capacity and never the only copy of any part.

SECTION 01 · Note

Assumptions in this document

Note
The request did not name the service, the regions, or the parts. This document assumes the Orders service with six parts: gateway, orders-api, orders-worker, Postgres, Redis, Kafka. It assumes the AWS regions us-east-1 and eu-west-1 with three zones each, and an active-passive write model. Change the counts in the table below and carry the change into the zone diagrams.

Two regions, one write primary

Route 53 answers with the nearest healthy region. The Postgres primary lives in us-east-1; eu-west-1 holds an asynchronous replica that lags by under two seconds in normal operation. Kafka topics mirror in the same direction, so eu-west-1 can serve reads and replay events but never accepts an order write while us-east-1 is healthy.

SECTION 02 · Architecture

Region layout

INFRA
Block diagram: 9 nodes, 9 connectionsus-east-1 · primaryeu-west-1 · secondaryGlobalRoute 53latency routingDNSLoadbalancerALBLBorders-apiGoSVC×12Postgres primaryPostgres 16DB×3Kafka3 brokersQUEUE×3LoadbalancerALBLBorders-apiGoSVC×6Postgres replicaPostgres 16DB×2Kafka3 brokersQUEUE×31234567
1US and default traffic2EU traffic3reads and writes4reads5writes, cross-region6async replication7MirrorMaker 2
LegendDNSDNSLBload balancerSVCserviceDBdatabaseQUEUEqueue×Nreplicascallsasync / optional

us-east-1, zone by zone

Every stateless part runs in all three zones with the same count, so the load balancer can drop a zone without a config change. The stateful parts differ by role: the Postgres primary is in zone a, the synchronous standby in b, and the asynchronous standby in c. Redis and Kafka each keep one node per zone; Kafka topics use replication factor 3 with min.insync.replicas=2, so a single zone outage never blocks a producer.

SECTION 03 · Cluster

us-east-1 compute

CLUSTER
Cluster diagramus-east-1azoneus-east-1bzoneus-east-1czonegatewayEnvoyGATEWAY×2orders-apiGoSVC×4orders-workerGoSVC×2gatewayEnvoyGATEWAY×2orders-apiGoSVC×4orders-workerGoSVC×2gatewayEnvoyGATEWAY×2orders-apiGoSVC×4orders-workerGoSVC×2order events via Kafkaorder events via Kafkaorder events via Kafka
LegendGATEWAYgatewaySVCservicecallsasync / optional

The data tier is where zones stop being interchangeable. Every orders-api copy writes to the primary in zone a, whichever zone it runs in. Redis is a cache with no persistence, so a lost Redis node costs a cache warm-up and nothing else.

SECTION 04 · Cluster

us-east-1 data

CLUSTER
Cluster diagramus-east-1azoneus-east-1bzoneus-east-1czoneredisRedis 7CACHE×1kafka broker 1Kafka 3.7QUEUE×1postgres primaryPostgres 16DB×1redisRedis 7CACHE×1kafka broker 2Kafka 3.7QUEUE×1postgres syncstandbyPostgres 16DB×1redisRedis 7CACHE×1kafka broker 3Kafka 3.7QUEUE×1postgres asyncstandbyPostgres 16DB×112345
1sync2async3partition replicas4partition replicas5partition replicas
LegendCACHEcacheQUEUEqueueDBdatabasecallsasync / optional

eu-west-1, zone by zone

The secondary region runs half the API count of the primary because it serves reads only. It keeps two Postgres replicas rather than three. Zone a receives the cross-region stream and zone b cascades from it, so one replica survives if either zone fails. Workers run one per zone; they process mirrored events for read models and stay idle for write-side jobs until a failover promotes the region.

SECTION 05 · Cluster

eu-west-1 compute

CLUSTER
Cluster diagrameu-west-1azoneeu-west-1bzoneeu-west-1czonegatewayEnvoyGATEWAY×2orders-apiGoSVC×2orders-workerGoSVC×1gatewayEnvoyGATEWAY×2orders-apiGoSVC×2orders-workerGoSVC×1gatewayEnvoyGATEWAY×2orders-apiGoSVC×2orders-workerGoSVC×1mirrored events via Kafkamirrored events via Kafkamirrored events via Kafka
LegendGATEWAYgatewaySVCservicecallsasync / optional

Zone c has no Postgres. Its orders-api copies read from zone a, which adds under one millisecond of cross-zone latency and keeps the replica count at two.

SECTION 06 · Cluster

eu-west-1 data

CLUSTER
Cluster diagrameu-west-1azoneeu-west-1bzoneeu-west-1czoneredisRedis 7CACHE×1kafka broker 1Kafka 3.7QUEUE×1postgres replicaPostgres 16DB×1redisRedis 7CACHE×1kafka broker 2Kafka 3.7QUEUE×1postgres cascadingreplicaPostgres 16DB×1redisRedis 7CACHE×1kafka broker 3Kafka 3.7QUEUE×11234
1cascade2partition replicas3partition replicas4partition replicas
LegendCACHEcacheQUEUEqueueDBdatabasecallsasync / optional

Copies of each part

The counts below are the steady-state minimum. Autoscaling raises orders-api and orders-worker above these numbers under load but never below them, and it never changes the stateful counts.

SECTION 07 · Comparison

Replica counts per part

PartPer zone (us-east-1)us-east-1 totalPer zone (eu-west-1)eu-west-1 totalAll regionsPlacement rule
gateway262612One Envoy pair per zone behind the regional ALB
orders-api4122618Spread evenly; pod anti-affinity forbids two pods on one node
orders-worker26139Consumer group per region; partitions rebalance on zone loss
Redis13136One node per zone; cache onlyno persistence
Kafka broker13136Replication factor 3, min.insync.replicas 2
Postgres131 (zones a, b)25Primary in us-east-1a; sync standby in b, async in c; two async replicas in eu-west-1

Totals count running instances, not nodes. A zone outage in us-east-1 leaves 8 orders-api copies, 2 Kafka brokers in sync, and a Postgres standby ready to promote.

View the Markdown
```meta
title: Orders service — regions, zones, and replicas
subtitle: Where each part of the Orders service runs, and how many copies of it exist.
tag: DRAFT
```

The Orders service runs in two regions. `us-east-1` takes all writes and most reads; `eu-west-1` serves European reads and takes over writes only on a declared failover. Each region spreads its parts across three availability zones. The loss of one zone removes at most a third of the capacity and never the only copy of any part.

```callout
tone: note
title: Assumptions in this document
body: "The request did not name the service, the regions, or the parts. This document assumes the Orders service with six parts: gateway, orders-api, orders-worker, Postgres, Redis, Kafka. It assumes the AWS regions us-east-1 and eu-west-1 with three zones each, and an active-passive write model. Change the counts in the table below and carry the change into the zone diagrams."
```

## Two regions, one write primary

Route 53 answers with the nearest healthy region. The Postgres primary lives in `us-east-1`; `eu-west-1` holds an asynchronous replica that lags by under two seconds in normal operation. Kafka topics mirror in the same direction, so `eu-west-1` can serve reads and replay events but never accepts an order write while `us-east-1` is healthy.

```block
preset: infra
title: Region layout
groups:
  - { id: global, col: 1, row: 1, cols: 1, rows: 1, label: Global }
  - { id: use1, col: 2, row: 1, cols: 1, rows: 4, label: "us-east-1 · primary" }
  - { id: euw1, col: 3, row: 1, cols: 1, rows: 4, label: "eu-west-1 · secondary" }
nodes:
  - { id: dns, col: 1, row: 1, kind: dns, name: Route 53, tech: latency routing }
  - { id: alb-use, col: 2, row: 1, kind: lb, name: Load balancer, tech: ALB }
  - { id: api-use, col: 2, row: 2, kind: service, name: orders-api, tech: Go, replicas: 12 }
  - { id: pg-use, col: 2, row: 3, kind: store, name: Postgres primary, tech: Postgres 16, replicas: 3 }
  - { id: kafka-use, col: 2, row: 4, kind: queue, name: Kafka, tech: "3 brokers", replicas: 3 }
  - { id: alb-euw, col: 3, row: 1, kind: lb, name: Load balancer, tech: ALB }
  - { id: api-euw, col: 3, row: 2, kind: service, name: orders-api, tech: Go, replicas: 6 }
  - { id: pg-euw, col: 3, row: 3, kind: store, name: Postgres replica, tech: Postgres 16, replicas: 2 }
  - { id: kafka-euw, col: 3, row: 4, kind: queue, name: Kafka, tech: "3 brokers", replicas: 3 }
edges:
  - dns -> alb-use: US and default traffic
  - dns -> alb-euw: EU traffic
  - alb-use -> api-use
  - alb-euw -> api-euw
  - api-use -> pg-use: reads and writes
  - api-euw -> pg-euw: reads
  - api-euw --> pg-use: writes, cross-region
  - pg-use --> pg-euw: async replication
  - kafka-use --> kafka-euw: MirrorMaker 2
```

## us-east-1, zone by zone

Every stateless part runs in all three zones with the same count, so the load balancer can drop a zone without a config change. The stateful parts differ by role: the Postgres primary is in zone `a`, the synchronous standby in `b`, and the asynchronous standby in `c`. Redis and Kafka each keep one node per zone; Kafka topics use replication factor 3 with `min.insync.replicas=2`, so a single zone outage never blocks a producer.

```cluster
title: us-east-1 compute
clusters:
  - { id: use1a, label: us-east-1a, kind: zone }
  - { id: use1b, label: us-east-1b, kind: zone }
  - { id: use1c, label: us-east-1c, kind: zone }
services:
  - { id: gw-a, cluster: use1a, label: gateway, kind: gateway, tech: Envoy, replicas: 2 }
  - { id: api-a, cluster: use1a, label: orders-api, kind: service, tech: Go, replicas: 4 }
  - { id: wrk-a, cluster: use1a, label: orders-worker, kind: service, tech: Go, replicas: 2 }
  - { id: gw-b, cluster: use1b, label: gateway, kind: gateway, tech: Envoy, replicas: 2 }
  - { id: api-b, cluster: use1b, label: orders-api, kind: service, tech: Go, replicas: 4 }
  - { id: wrk-b, cluster: use1b, label: orders-worker, kind: service, tech: Go, replicas: 2 }
  - { id: gw-c, cluster: use1c, label: gateway, kind: gateway, tech: Envoy, replicas: 2 }
  - { id: api-c, cluster: use1c, label: orders-api, kind: service, tech: Go, replicas: 4 }
  - { id: wrk-c, cluster: use1c, label: orders-worker, kind: service, tech: Go, replicas: 2 }
edges:
  - gw-a -> api-a
  - gw-b -> api-b
  - gw-c -> api-c
  - api-a --> wrk-a: order events via Kafka
  - api-b --> wrk-b: order events via Kafka
  - api-c --> wrk-c: order events via Kafka
```

The data tier is where zones stop being interchangeable. Every `orders-api` copy writes to the primary in zone `a`, whichever zone it runs in. Redis is a cache with no persistence, so a lost Redis node costs a cache warm-up and nothing else.

```cluster
title: us-east-1 data
clusters:
  - { id: use1a, label: us-east-1a, kind: zone }
  - { id: use1b, label: us-east-1b, kind: zone }
  - { id: use1c, label: us-east-1c, kind: zone }
services:
  - { id: redis-a, cluster: use1a, label: redis, kind: cache, tech: Redis 7, replicas: 1 }
  - { id: kafka-a, cluster: use1a, label: kafka broker 1, kind: queue, tech: Kafka 3.7, replicas: 1 }
  - { id: pg-a, cluster: use1a, label: postgres primary, kind: store, tech: Postgres 16, replicas: 1 }
  - { id: redis-b, cluster: use1b, label: redis, kind: cache, tech: Redis 7, replicas: 1 }
  - { id: kafka-b, cluster: use1b, label: kafka broker 2, kind: queue, tech: Kafka 3.7, replicas: 1 }
  - { id: pg-b, cluster: use1b, label: postgres sync standby, kind: store, tech: Postgres 16, replicas: 1 }
  - { id: redis-c, cluster: use1c, label: redis, kind: cache, tech: Redis 7, replicas: 1 }
  - { id: kafka-c, cluster: use1c, label: kafka broker 3, kind: queue, tech: Kafka 3.7, replicas: 1 }
  - { id: pg-c, cluster: use1c, label: postgres async standby, kind: store, tech: Postgres 16, replicas: 1 }
edges:
  - pg-a -> pg-b: sync
  - pg-a --> pg-c: async
  - kafka-a -> kafka-b: partition replicas
  - kafka-b -> kafka-c: partition replicas
  - kafka-c -> kafka-a: partition replicas
```

## eu-west-1, zone by zone

The secondary region runs half the API count of the primary because it serves reads only. It keeps two Postgres replicas rather than three. Zone `a` receives the cross-region stream and zone `b` cascades from it, so one replica survives if either zone fails. Workers run one per zone; they process mirrored events for read models and stay idle for write-side jobs until a failover promotes the region.

```cluster
title: eu-west-1 compute
clusters:
  - { id: euw1a, label: eu-west-1a, kind: zone }
  - { id: euw1b, label: eu-west-1b, kind: zone }
  - { id: euw1c, label: eu-west-1c, kind: zone }
services:
  - { id: egw-a, cluster: euw1a, label: gateway, kind: gateway, tech: Envoy, replicas: 2 }
  - { id: eapi-a, cluster: euw1a, label: orders-api, kind: service, tech: Go, replicas: 2 }
  - { id: ewrk-a, cluster: euw1a, label: orders-worker, kind: service, tech: Go, replicas: 1 }
  - { id: egw-b, cluster: euw1b, label: gateway, kind: gateway, tech: Envoy, replicas: 2 }
  - { id: eapi-b, cluster: euw1b, label: orders-api, kind: service, tech: Go, replicas: 2 }
  - { id: ewrk-b, cluster: euw1b, label: orders-worker, kind: service, tech: Go, replicas: 1 }
  - { id: egw-c, cluster: euw1c, label: gateway, kind: gateway, tech: Envoy, replicas: 2 }
  - { id: eapi-c, cluster: euw1c, label: orders-api, kind: service, tech: Go, replicas: 2 }
  - { id: ewrk-c, cluster: euw1c, label: orders-worker, kind: service, tech: Go, replicas: 1 }
edges:
  - egw-a -> eapi-a
  - egw-b -> eapi-b
  - egw-c -> eapi-c
  - eapi-a --> ewrk-a: mirrored events via Kafka
  - eapi-b --> ewrk-b: mirrored events via Kafka
  - eapi-c --> ewrk-c: mirrored events via Kafka
```

Zone `c` has no Postgres. Its `orders-api` copies read from zone `a`, which adds under one millisecond of cross-zone latency and keeps the replica count at two.

```cluster
title: eu-west-1 data
clusters:
  - { id: euw1a, label: eu-west-1a, kind: zone }
  - { id: euw1b, label: eu-west-1b, kind: zone }
  - { id: euw1c, label: eu-west-1c, kind: zone }
services:
  - { id: eredis-a, cluster: euw1a, label: redis, kind: cache, tech: Redis 7, replicas: 1 }
  - { id: ekafka-a, cluster: euw1a, label: kafka broker 1, kind: queue, tech: Kafka 3.7, replicas: 1 }
  - { id: epg-a, cluster: euw1a, label: postgres replica, kind: store, tech: Postgres 16, replicas: 1 }
  - { id: eredis-b, cluster: euw1b, label: redis, kind: cache, tech: Redis 7, replicas: 1 }
  - { id: ekafka-b, cluster: euw1b, label: kafka broker 2, kind: queue, tech: Kafka 3.7, replicas: 1 }
  - { id: epg-b, cluster: euw1b, label: postgres cascading replica, kind: store, tech: Postgres 16, replicas: 1 }
  - { id: eredis-c, cluster: euw1c, label: redis, kind: cache, tech: Redis 7, replicas: 1 }
  - { id: ekafka-c, cluster: euw1c, label: kafka broker 3, kind: queue, tech: Kafka 3.7, replicas: 1 }
edges:
  - epg-a --> epg-b: cascade
  - ekafka-a -> ekafka-b: partition replicas
  - ekafka-b -> ekafka-c: partition replicas
  - ekafka-c -> ekafka-a: partition replicas
```

## Copies of each part

The counts below are the steady-state minimum. Autoscaling raises `orders-api` and `orders-worker` above these numbers under load but never below them, and it never changes the stateful counts.

```table
title: Replica counts per part
columns:
  - Part
  - { label: Per zone (us-east-1), align: r }
  - { label: us-east-1 total, align: r }
  - { label: Per zone (eu-west-1), align: r }
  - { label: eu-west-1 total, align: r }
  - { label: All regions, align: r, highlight: true }
  - Placement rule
rows:
  - [{ v: gateway, lead: true }, 2, 6, 2, 6, { v: 12, highlight: true }, One Envoy pair per zone behind the regional ALB]
  - [{ v: orders-api, lead: true }, 4, 12, 2, 6, { v: 18, highlight: true }, Spread evenly; pod anti-affinity forbids two pods on one node]
  - [{ v: orders-worker, lead: true }, 2, 6, 1, 3, { v: 9, highlight: true }, Consumer group per region; partitions rebalance on zone loss]
  - [{ v: Redis, lead: true }, 1, 3, 1, 3, { v: 6, highlight: true }, One node per zone; cache only, no persistence]
  - [{ v: Kafka broker, lead: true }, 1, 3, 1, 3, { v: 6, highlight: true }, "Replication factor 3, min.insync.replicas 2"]
  - [{ v: Postgres, lead: true }, 1, 3, { v: "1 (zones a, b)", tone: muted }, 2, { v: 5, highlight: true }, "Primary in us-east-1a; sync standby in b, async in c; two async replicas in eu-west-1"]
note: "Totals count running instances, not nodes. A zone outage in us-east-1 leaves 8 orders-api copies, 2 Kafka brokers in sync, and a Postgres standby ready to promote."
```