What We're Building
A Nigerian fintech has two offices, Lagos and Abuja and wants:
- Both offices on the same private network, even though they sit in different parts of the world
- A web app running on a server in each office
- Traffic automatically routed to whichever office is closest to the user, with automatic failover if one office's server goes down
To simulate this on Azure, Lagos lives in East US and Abuja lives in South Africa North two genuinely different Azure regions, connected privately, with a global load balancer deciding where to send traffic.
By the end of this guide, you'll have a working multi-region setup you can test from your own terminal.
What you'll need
- An Azure account (the free tier works fine)
- Basic comfort with the Azure Portal
- A terminal that can run
sshandcurl(Git Bash, macOS/Linux terminal, or Cloud Shell)
Step 1: Create a Resource Group
A resource group is just a logical folder that holds everything we build, so it's easy to manage or delete later as one unit.
- In the Azure Portal, search "Resource groups" → + Create
-
Resource group name:
fintech-rg - Region: pick any region for the resource group itself, it doesn't have to match the resources inside it
- Review + Create → Create
Step 2: Create Two Virtual Networks (VNets)
A VNet is a private network inside Azure. We need one for each branch office, in two different regions.
VNet for Lagos (East US)
- Search "Virtual networks" → + Create
- Resource group:
fintech-rg - Name:
lagos-vnet - Region: East US
- Leave the default address space and subnet, or customize if you prefer
- Review + Create → Create
VNet for Abuja (South Africa North)
Repeat the same steps:
- Name:
abuja-vnet - Region: South Africa North
- Review + Create → Create
Step 3: Peer the Two VNets Together
VNet Peering connects the two networks so resources inside them can talk to each other using private IP addresses, as if they were on the same local network, no public internet involved.
Peering needs to be set up from both sides once from Lagos's VNet pointing to Abuja, and once from Abuja's VNet pointing to Lagos.
From the Lagos VNet
- Open
lagos-vnet→ left menu → Peerings → + Add -
This virtual network:
- Peering link name:
lagos-to-abuja - Allow traffic to remote virtual network: ✅ enabled
- Peering link name:
-
Remote virtual network:
- Peering link name:
abuja-to-lagos - Virtual network: select
abuja-vnet - Allow traffic to remote virtual network: ✅ enabled
- Peering link name:
- Add
This single step actually creates both sides of the peering at once.
Confirm the Peering Is Connected
- Go back to
lagos-vnet→ Peerings - You should see the peering listed with status: Connected
- Check
abuja-vnet→ Peerings too — it should show Connected from its side as well
Step 4: Create a VM in Each VNet
VM for Lagos
- Search "Virtual machines" → + Create
- Resource group:
fintech-rg - VM name:
lagos-vm - Region: East US
- Image: Ubuntu Server (any recent LTS version)
- Size: the default/smallest size is fine for this project
- Authentication: SSH public key (recommended) or password
- Username:
lagosvm(or whatever username you prefer, just stay consistent for the rest of the guide) -
Networking tab: Virtual network → select
lagos-vnet - Review + Create → Create
VM for Abuja
Repeat with:
- VM name:
abuja-vm - Region: South Africa North
- Username:
abujavm - Virtual network:
abuja-vnet
Once both VMs are created, note down:
- Each VM's public IP (used to SSH in)
- Each VM's private IP (used for the ping test later)
In this guide, the private IPs are:
- Lagos VM private IP:
10.0.0.4 - Abuja VM private IP:
10.1.0.4
(Yours may be different — always use the actual IP shown in your VM's Overview or Networking tab.)
Step 5: Secure SSH Access and Connect to Each VM
If you're using an SSH key pair, make sure your private key file has the correct permissions before connecting, otherwise SSH will refuse to use it:
chmod 700 lagosvm_key.pem
(Do the same for the Abuja key if you're using a separate one.)
Connect to the Lagos VM:
ssh -i lagosvm_key.pem lagosvm@<lagos-vm-public-ip>
Connect to the Abuja VM in a separate terminal tab:
ssh -i abujavm_key.pem abujavm@<abuja-vm-public-ip>
Step 6: Install and Start a Web Server on Each VM
Run this on both VMs:
sudo apt update && sudo apt upgrade -y
sudo apt install apache2 -y
sudo systemctl start apache2
sudo systemctl enable apache2
-
apt update && upgraderefreshes the package list and applies any pending updates -
apache2is the web server that will respond to HTTP requests -
enablemakes sure Apache automatically restarts if the VM ever reboots
Confirm Apache is running on each VM:
sudo systemctl status apache2
You should see active (running) in green.
Step 7: Test the Private Network Connection (Ping Test)
This is the moment that proves the VNet peering actually works — two VMs, in two different regions, reaching each other over a private connection.
From the Lagos VM, ping Abuja's private IP:
ping 10.1.0.4
From the Abuja VM, ping Lagos's private IP:
ping 10.0.0.4
If peering is working correctly, you'll see successful replies on both sides, something like:
64 bytes from 10.1.0.4: icmp_seq=1 ttl=64 time=142 ms
Press Ctrl + C to stop the ping.
⚠️ Note: If you don't get replies, double check that each VM's Network Security Group (NSG) allows inbound traffic from the peered VNet (the default
AllowVnetInBoundrule usually covers this automatically).
Step 8: Customize Each Web Page So You Can Tell Them Apart
To visually confirm which server is responding later (especially once the load balancer is involved), give each VM a distinct homepage.
On the Lagos VM:
echo "<h1>Hello from Lagos Server</h1>" | sudo tee /var/www/html/index.html
On the Abuja VM:
echo "<h1>Hello from Abuja Server</h1>" | sudo tee /var/www/html/index.html
Test it directly using each VM's public IP in a browser:
http://<lagos-vm-public-ip>
http://<abuja-vm-public-ip>
You should see the matching "Hello from..." message for each one.
Step 9: Open Port 80 on Both VMs
Apache runs on port 80, so each VM's NSG needs to allow inbound HTTP traffic — otherwise external requests (including from the load balancer) won't be able to reach it.
- Open each VM → Networking tab → Add inbound port rule
- Settings:
- Destination port:
80 - Protocol:
TCP - Action:
Allow - Give the rule a name (anything descriptive works, e.g.
Allow-HTTP)
- Destination port:
- Add
- Repeat for the other VM
Step 10: Create the Regional Load Balancer for Lagos
Since Lagos and Abuja are in different regions, we can't use one single load balancer to cover both — a standard Azure Load Balancer only operates within a single region. We need one regional load balancer per region, and later, a Global Load Balancer sitting on top of both.
10.1 — Create the Public IP
- Search "Public IP addresses" → + Create
- Give it a name (e.g.
lagos-lb-ip) - SKU: Standard
- Tier: Regional
- Region: East US
- Assignment: Static
- Review + Create → Create
10.2 — Create the Load Balancer
- Search "Load balancers" → + Create
- Give it a name (e.g.
lagos-lb) - Region: East US
- SKU: Standard
- Type: Public
- Tier: Regional
-
Frontend IP configuration: add a frontend IP, give it a name, and select the public IP you just created (
lagos-lb-ip) — this becomes your regional frontend IP, in this guide20.121.242.74 - Skip backend pools and rules for now — we'll add them after creation for a cleaner setup
- Review + Create → Create
10.3 — Add the Backend Pool
- Open your Lagos load balancer → Backend pools → + Add
- Give it a name
- Virtual network: select
lagos-vnet - Backend pool configuration: NIC
- Click + Add under the IP configurations table → select
lagos-vm - Save
10.4 — Add a Health Probe
- Health probes → + Add
- Give it a name
- Protocol: HTTP
- Port:
80 - Path:
/ - Interval: 5–15 seconds
- Add
10.5 — Add the Load Balancing Rule
- Load balancing rules → + Add
- Give it a name
- Frontend IP: select the frontend IP you created
- Backend pool: select the backend pool you created
- Health probe: select the probe you created
- Protocol: TCP, Port:
80, Backend port:80 - Add
10.6 — Test the Lagos Load Balancer
From your terminal:
curl http://20.121.242.74
(replace with your actual Lagos load balancer frontend IP)
You should see the "Hello from Lagos Server" response.
Step 11: Create the Regional Load Balancer for Abuja
Repeat all of Step 10, but for the Abuja region:
- Public IP: give it a name, Region: South Africa North → in this guide, the resulting frontend IP is
20.87.39.70 - Load Balancer: give it a name, Region: South Africa North
- Backend pool: Virtual network →
abuja-vnet, addabuja-vm - Health probe and rule: same settings as before (HTTP/80/
/, TCP/80→80)
Test it:
curl http://20.87.39.70
You should see "Hello from Abuja Server."
⚠️ Important: Don't move to the next step until both regional load balancers pass this test independently. The Global Load Balancer depends on both of these already working correctly.
Step 12: Create the Global Load Balancer
The Global Load Balancer sits above both regional load balancers and decides which region to send each user's request to, based on which one is geographically closest and healthy.
12.1 — Create the Global Public IP
- Search "Public IP addresses" → + Create
- Give it a name (e.g.
global-lb-ip) - SKU: Standard
- Tier: Global
- Region: must be one of Azure's supported home regions for global resources, examples include
East US 2,West Europe,Southeast Asia,West US,North Europe,Central US - Assignment: Static
- Review + Create → Create
In this guide, the resulting global IP is 20.15.1.61.
12.2 — Create the Global Load Balancer
- Search "Load balancers" → + Create
- Give it a name (e.g.
global-lb) - Region: the same home region you used for the global IP (e.g.
East US 2) - SKU: Standard
- Tier: Global ⚠️ this is the setting that matters most here — don't select Regional
-
Frontend IP configuration: add a frontend IP, give it a name, and select your
global-lb-ip - Skip backend pools and rules in the wizard
- Review + Create → Create
12.3 — Add the Backend Pool
- Open your Global load balancer → Backend pools → + Add
- Give it a name
- Under the configuration table, click + Add
- Type: Load Balancer (not NIC, not IP address)
- Add your Lagos load balancer
- Click + Add again and add your Abuja load balancer
- Confirm both regional load balancers now appear in the table
- Save
12.4 — Add the Load Balancing Rule
- Load balancing rules → + Add
- Give it a name
- Frontend IP: your global frontend IP
- Backend pool: your global backend pool
- Protocol: TCP, Port:
80, Backend port:80
The backend port here must match the frontend port used in both regional load balancer rules — in this case, both use port 80, so we're consistent.
- Add
Step 13: Test the Global Load Balancer
curl http://20.15.1.61
(replace with your actual global load balancer IP)
You should get back a response from whichever region is closest to you, for example, "Hello from Lagos Server."
This is expected behavior: the Global Load Balancer uses geo-proximity routing, not round robin. It always routes you to the closest healthy region, not a random alternating split.
Step 14: Test Automatic Failover
To prove the system can actually fail over between regions, we'll simulate one region going down.
SSH into the Lagos VM and stop Apache:
sudo systemctl stop apache2
Now curl the global load balancer again:
curl http://20.15.1.61
This time, the response should switch to "Hello from Abuja Server" Azure detected that the Lagos region's health probe failed, removed it from rotation, and automatically routed traffic to the healthy Abuja region instead.
Once you're done testing, restart Apache on the Lagos VM so it's back in rotation:
sudo systemctl start apache2
Recap: What We Actually Built
Client
↓
Global Load Balancer (home region, e.g. East US 2)
↓ ↓
Regional LB - Lagos Regional LB - Abuja
(East US) (South Africa North)
↓ ↓
lagos-vm abuja-vm
↳ peered privately with abuja-vm via VNet Peering
This setup demonstrates three real-world cloud concepts at once:
- Private cross-region connectivity (VNet Peering)
- Regional high availability (each region's own load balancer and health probe)
- Global resilience and failover (the Global Load Balancer routing around an unhealthy region automatically)
If you build this yourself, try the failover test a few times — watching traffic automatically reroute in real time is genuinely satisfying, and it's the same underlying pattern real fintechs use to stay online across regions.
Got stuck somewhere or have a question about a specific step? Drop a comment below 👇






















Top comments (0)