Guide

Multi-region failover with a WireGuard mesh

Advanced40 min readUpdated July 8, 2026
Short answer

Three instances in three countries, meshed over WireGuard, with the application bound only to the mesh and a health-checked DNS record in front, gives genuine fault tolerance for under $110 a month. The design constraint is database replication: synchronous within a region, asynchronous across them.

01 Choose three independent failure domains

Different countries, ideally different transit mixes. Amsterdam, Ashburn and Singapore is the classic triangle. Three is the minimum for quorum — two gives you a split-brain problem rather than redundancy.

02 Build the mesh

Each node gets a stable private address. Every node peers with every other node; with three nodes that is three tunnels.

# node A — /etc/wireguard/mesh.conf
[Interface]
Address = 10.10.0.1/24
ListenPort = 51821
PrivateKey = <A private>

[Peer]                       # node B
PublicKey = <B public>
Endpoint = b.example.net:51821
AllowedIPs = 10.10.0.2/32
PersistentKeepalive = 25

[Peer]                       # node C
PublicKey = <C public>
Endpoint = c.example.net:51821
AllowedIPs = 10.10.0.3/32
PersistentKeepalive = 25

03 Bind services to the mesh only

The database, the cache and the internal API should listen on 10.10.0.x, never on the public address. This removes an entire class of exposure without a single firewall rule.

04 Replicate the database appropriately

Synchronous replication across regions is impractical — a 160 ms round trip becomes the floor for every write. Use asynchronous replication across regions and know your recovery point objective.

05 Health-check at the DNS layer

Short TTLs plus health-checked failover records, or anycast if your regions support it. Then run a failure drill: kill a region deliberately, on a weekday, while you are watching.

Frequently asked questions

Why not just buy a bigger server?

A bigger server has the same number of failure domains as a small one: one. Availability comes from independence, not from capacity.

How far apart can etcd or Postgres synchronous replicas be?

Keep synchronous replicas within about 100 ms of each other. Beyond that the write latency becomes the dominant cost of every transaction.