Skip to main content

Theoretical Foundation: Create and configure virtual network peering


1. Initial Intuition​

In the previous module, we learned that VNets are completely isolated from each other by default. A VM in vnet-production and a VM in vnet-development cannot communicate, just like two separate buildings have no connecting corridor.

VNet Peering is that corridor: a direct connection between two VNets that allows resources in each one to communicate as if they were on the same network. There's no additional hardware, no encryption (traffic already travels through Microsoft's private backbone network), no gateway, and latency is the same as within a single VNet.

The most accurate analogy is a walkway between two corporate buildings: the buildings remain independent structures, with their own internal rules, but people can move between them directly and quickly, without going outside to the street.


2. Context​

VNet Peering solves one of the most common problems in medium and large-scale Azure environments: how to efficiently connect multiple VNets. It forms the foundation of two widely used architectures:

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

Alternatives to VNet Peering for connecting VNets are VPN Gateway (more expensive, slower, via internet or encrypted tunnel) or ExpressRoute (for dedicated connections with on-premises). Peering is always the first choice when the need is to connect two Azure VNets, due to its simplicity and performance.


3. Building the Concepts​

3.1 What is a Peering: Bidirectional Nature with Two Entities​

This is the most important and most frequently confused concept about VNet Peering: a peering is not a single object; it's always two separate objects.

When you connect VNet-A and VNet-B, you create:

  1. A peering from VNet-A towards VNet-B (configured on VNet-A's side)
  2. A peering from VNet-B towards VNet-A (configured on VNet-B's side)

Both need to exist and be in the Connected state for communication to work. If only one side is created, the state remains Initiated, and traffic doesn't flow.

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

3.2 Types of Peering​

TypeDescriptionLatency
Local VNet PeeringVNets in the same Azure regionSame as within a single VNet
Global VNet PeeringVNets in different regionsSlightly higher, uses Microsoft's global backbone

Global VNet Peering allows connecting, for example, a VNet in Brazil South with a VNet in East US. Traffic travels through Microsoft's private network, not the public internet.

Global Peering Restriction: some resources don't support traffic via Global VNet Peering. The most important is the Azure Load Balancer Standard (Basic tier): VMs in one VNet cannot be reached by resources in a peered VNet in a different region using the Load Balancer IP. Direct access via VM IP works normally.

3.3 Peering Configurations​

Each side of the peering has independent configurations. The most important ones are:

ConfigurationOn sideWhat it controls
Allow virtual network accessBothWhether resources from the destination VNet are accessible. If disabled, traffic doesn't flow even with the peering connected.
Allow forwarded trafficBothWhether traffic that was forwarded by an NVA (network virtual appliance) can use this peering. Crucial for hub-spoke.
Allow gateway transitSide that has the gatewayAllows the other VNet to use this VNet's gateway (VPN or ExpressRoute). Enables on-premises connectivity via hub.
Use remote gatewaysSide that does NOT have the gatewayEnables using the other VNet's gateway. Must be enabled together with "Allow gateway transit" on the other side.

The combination of Allow gateway transit + Use remote gateways is what allows spoke VNets in a hub-spoke architecture to access the on-premises network through the VPN Gateway located in the hub.

3.4 Non-Transitivity: The Fundamental Concept​

VNet Peering is non-transitive. This means that if A is connected to B, and B is connected to C, this doesn't imply that A can communicate with C.

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

For A to communicate with C, it's necessary to:

  • Option 1: Create a direct peering between A and C
  • Option 2: Use an NVA (Network Virtual Appliance, like Azure Firewall) in VNet-B to forward traffic, with User Defined Routes (UDRs) configured and "Allow forwarded traffic" enabled in the peerings

Non-transitivity is why hub-spoke architecture requires special configuration: the hub needs to have an NVA or firewall to route traffic between spokes, and the peerings need to have "Allow forwarded traffic" enabled.


4. Structural View​

Point-to-Point Peering​

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

Hub-Spoke Architecture with Peering and Gateway Transit​

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

In this topology:

  • Spoke1 accesses on-premises via gateway in the Hub (thanks to gateway transit)
  • Spoke2 accesses on-premises via gateway in the Hub (same mechanism)
  • Traffic between Spoke1 and Spoke2 goes through the Firewall in the Hub (by UDRs, not direct peering)
  • The Hub centralizes all shared services

5. Practical Operation​

How Traffic Flows in a Peering​

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

When a peering is created, Azure automatically adds peering routes to the effective route tables of NICs in both VNets. These routes have the remote VNet prefix and next hop type VNetPeering. You can see these routes by checking the "Effective Routes" of any NIC via Network Watcher.

Important and Non-Obvious Behaviors​

Peering doesn't prevent NSGs from blocking traffic: creating a peering between two VNets doesn't automatically open all traffic flows. NSGs associated with subnets or NICs in the VNets still apply. An NSG that blocks traffic from 10.2.0.0/16 will continue blocking even after the peering is created.

Address space changes require peering action: if you add a new CIDR block to a VNet that already has peerings, you need to synchronize the peerings for the new routes to be propagated. In the portal, there's a "Sync" button in the peering configuration. Without synchronization, peered VNets cannot reach the new addresses.

Peering between different subscriptions: fully supported, but requires the user creating the peering to have permission in both VNets. The minimum required role is Network Contributor (or a custom role with Microsoft.Network/virtualNetworks/virtualNetworkPeerings/write) in both VNets.

Peering cost: unlike VNet creation itself, VNet Peering has costs based on transferred traffic volume. Local peering (same region) and global peering (between regions) have different prices, with global being more expensive. Plan this into cost sizing.

Cannot use overlapping address spaces: if VNet-A has 10.0.0.0/16 and VNet-B also has 10.0.0.0/16, the peering fails. The spaces must be completely distinct and non-overlapping.


6. Implementation Methods​

6.1 Azure Portal​

When to use: one-time peering creation, status visualization, diagnostics.

Path: Virtual Networks > [select VNet] > Peerings > Add

The peering creation form in the portal has an important convenience: when creating a peering from VNet-A to VNet-B, the portal offers the option to create the reverse peering (VNet-B to VNet-A) at the same time, provided the user has permission in both VNets. This avoids the error of creating only one side.

Creation fields:

  • Peering link name (local side): name of the peering in the source VNet
  • Peering link name (remote side): name of the peering in the destination VNet
  • Virtual network: the destination VNet (supports search by name, different subscription, different tenant)
  • Traffic forwarded from remote virtual network: "Allow forwarded traffic"
  • Virtual network gateway or Route Server: "Allow gateway transit" or "Use remote gateways"

6.2 Azure CLI​

Create peering on both sides (recommended operation: create both in sequence):

# Peering from VNet-A to VNet-B
az network vnet peering create \
--name peering-production-to-dev \
--vnet-name vnet-production \
--resource-group rg-networking \
--remote-vnet /subscriptions/<sub-id>/resourceGroups/rg-networking/providers/Microsoft.Network/virtualNetworks/vnet-dev \
--allow-vnet-access true \
--allow-forwarded-traffic true

# Peering from VNet-B to VNet-A
az network vnet peering create \
--name peering-dev-to-production \
--vnet-name vnet-dev \
--resource-group rg-networking \
--remote-vnet /subscriptions/<sub-id>/resourceGroups/rg-networking/providers/Microsoft.Network/virtualNetworks/vnet-production \
--allow-vnet-access true \
--allow-forwarded-traffic true

Create peering between VNets in different subscriptions:

# Get full VNet IDs
VNET_PROD_ID=$(az network vnet show \
--name vnet-production \
--resource-group rg-networking \
--subscription <sub-production-id> \
--query id -o tsv)

VNET_DEV_ID=$(az network vnet show \
--name vnet-dev \
--resource-group rg-dev \
--subscription <sub-dev-id> \
--query id -o tsv)

# Peering from Prod to Dev (execute with Prod subscription context)
az network vnet peering create \
--name peering-prod-to-dev \
--vnet-name vnet-production \
--resource-group rg-networking \
--subscription <sub-production-id> \
--remote-vnet $VNET_DEV_ID \
--allow-vnet-access true

# Peering from Dev to Prod (execute with Dev subscription context)
az network vnet peering create \
--name peering-dev-to-prod \
--vnet-name vnet-dev \
--resource-group rg-dev \
--subscription <sub-dev-id> \
--remote-vnet $VNET_PROD_ID \
--allow-vnet-access true

Check peering status:

az network vnet peering list \
--vnet-name vnet-production \
--resource-group rg-networking \
--query "[].{Name:name, State:peeringState, RemoteVNet:remoteVirtualNetwork.id}" \
--output table

Sync peering after address space change:

az network vnet peering sync \
--name peering-production-to-dev \
--vnet-name vnet-production \
--resource-group rg-networking

Create peering with gateway transit (Hub side):

az network vnet peering create \
--name peering-hub-to-spoke1 \
--vnet-name vnet-hub \
--resource-group rg-hub \
--remote-vnet <spoke1-vnet-id> \
--allow-vnet-access true \
--allow-forwarded-traffic true \
--allow-gateway-transit true

Create peering with use remote gateways (Spoke side):

az network vnet peering create \
--name peering-spoke1-to-hub \
--vnet-name vnet-spoke1 \
--resource-group rg-spoke1 \
--remote-vnet <hub-vnet-id> \
--allow-vnet-access true \
--allow-forwarded-traffic true \
--use-remote-gateways true

Prerequisite: --use-remote-gateways only works if the gateway in the Hub is already provisioned and --allow-gateway-transit true is configured in the Hub-side peering.

6.3 PowerShell​

# Get VNet references
$vnetProd = Get-AzVirtualNetwork -Name "vnet-production" -ResourceGroupName "rg-networking"
$vnetDev = Get-AzVirtualNetwork -Name "vnet-dev" -ResourceGroupName "rg-networking"

# Create peering from Prod to Dev
Add-AzVirtualNetworkPeering `
-Name "peering-production-to-dev" `
-VirtualNetwork $vnetProd `
-RemoteVirtualNetworkId $vnetDev.Id `
-AllowForwardedTraffic `
-AllowVirtualNetworkAccess

# Create peering from Dev to Prod
Add-AzVirtualNetworkPeering `
-Name "peering-dev-to-production" `
-VirtualNetwork $vnetDev `
-RemoteVirtualNetworkId $vnetProd.Id `
-AllowForwardedTraffic `
-AllowVirtualNetworkAccess

# Check status
Get-AzVirtualNetworkPeering `
-VirtualNetworkName "vnet-production" `
-ResourceGroupName "rg-networking" |
Select-Object Name, PeeringState, RemoteVirtualNetwork

6.4 Bicep​

// Peering from VNet-A to VNet-B
resource peeringAtoB 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2023-05-01' = {
name: '${vnetA.name}/peering-a-to-b'
properties: {
remoteVirtualNetwork: {
id: vnetB.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}

// Peering from VNet-B to VNet-A
resource peeringBtoA 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2023-05-01' = {
name: '${vnetB.name}/peering-b-to-a'
properties: {
remoteVirtualNetwork: {
id: vnetA.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
dependsOn: [peeringAtoB]
}

The dependsOn ensures the first peering is created before the second, avoiding race conditions.


7. Control and Security​

NSGs Still Apply with Peering​

Creating a peering doesn't change NSG behavior. An NSG that blocks traffic from 10.2.0.0/16 continues blocking even with active peering. This is positive from a security perspective: peering connects the networks, but traffic controls (NSGs, Azure Firewall, UDRs) determine what can flow.

Recommended practice: when creating peerings, review NSGs in both VNets to ensure necessary rules are configured. NSGs that use "VirtualNetwork" as source/destination automatically include peered VNets, which may be more permissive than expected.

Required Permissions to Create Peerings​

OperationRequired permissionRole that includes
Create peering in VNet-AMicrosoft.Network/virtualNetworks/virtualNetworkPeerings/write in VNet-ANetwork Contributor, Owner
Create peering in VNet-B (reverse side)Microsoft.Network/virtualNetworks/virtualNetworkPeerings/write in VNet-BNetwork Contributor in VNet-B
Create peering between subscriptionsPermissions in both VNets in their respective subscriptionsNetwork Contributor in both

For peering between different tenants, explicit permission must be assigned to the principal from the other tenant before creating the peering.

Tracking Traffic between Peered VNets​

Network Watcher Flow Logs can be enabled in each VNet to log traffic flowing through NICs. To specifically track traffic via peering, the effective routes of a NIC will show entries with NextHopType: VNetPeering.


8. Decision Making​

VNet Peering vs. other VNet connectivity options​

SituationBest optionReason
Two VNets in the same Azure regionLocal VNet PeeringLower latency, traffic-based cost, simple to configure
Two VNets in different regionsGlobal VNet PeeringSame model, uses Microsoft private backbone
Azure VNet and on-premises networkVPN Gateway or ExpressRoutePeering doesn't connect to on-premises; requires gateway
Many VNets need centralized connectivityHub-spoke with peeringsScales well, centralizes services
Need high security and inspection between VNetsHub-spoke with Azure Firewall in hubPeering + UDRs + Firewall for traffic inspection
Transitive connectivity between dozens of VNetsAzure Virtual WANSolves transitivity natively, Microsoft-managed

When to use "Allow forwarded traffic"?​

SituationEnable?Reason
Direct peering without NVA in the pathNot necessaryTraffic goes directly between the VNets
Hub-spoke architecture with Firewall/NVA in hubRequiredThe NVA forwards traffic between spokes; without this, forwarded traffic is dropped
Spoke needs to exit to internet via NVA in hubRequiredSame principle: outbound traffic is forwarded by the NVA

9. Best Practices​

Create both sides of peering in the same operation or pipeline: the window between creating one side and the other is a period where traffic still doesn't flow. In Infrastructure as Code pipelines, create both resources in the same template to ensure atomicity.

Use descriptive and standardized peering names: a pattern like peering-[source-vnet]-to-[destination-vnet] (e.g., peering-hub-to-production) makes the direction and involved VNets immediately clear. In environments with dozens of peerings, ambiguous names make maintenance much more difficult.

Document the peering topology: in complex environments, maintain an updated diagram of which VNets are connected to each other, via what type of peering (local or global) and what special configurations (gateway transit, etc.) are active. Tools like Network Watcher Topology can generate this view automatically.

Plan address spaces without overlap for all future VNets: the biggest obstacle to peering is address overlap. In growing companies, defining from the beginning an IPAM plan that allocates unique blocks for each VNet (production, dev, staging, hub, and each region) avoids future rework.

For hub-spoke: enable "Allow forwarded traffic" on spoke peerings from creation: even if you don't have a Firewall/NVA in the hub now, enabling this option from the start avoids having to modify the peerings later, when you add the Firewall and discover that forwarded traffic is being dropped.


10. Common Errors​

Creating only one side of peering and confusing "Initiated" state with "Connected"

Peering remains in Initiated state when only one side has been created. Resources in both VNets cannot communicate. The administrator checks the peering on side A, sees the state and thinks something is wrong with the network, spends hours diagnosing, when the solution is simply creating the peering on side B. The portal facilitates this by offering simultaneous creation of both sides.

Adding address space to VNet without synchronizing peerings

The company adds a second CIDR block (10.1.0.0/16) to the production VNet that already has peering. VMs in the new addresses (10.1.x.x) cannot communicate with VMs in the peered VNet. Peering routes were not automatically updated. The solution is to synchronize the peering ("Sync" button in portal or az network vnet peering sync in CLI).

Assuming peering is transitive

The development team creates VNet-Dev peered with VNet-Hub, and the data team creates VNet-Data also peered with VNet-Hub. They expect Dev and Data to communicate via Hub. It doesn't work because peering is not transitive. To connect Dev and Data, a direct peering between them is needed, or a Firewall in Hub with UDRs forwarding traffic.

Enabling "Use remote gateways" when the hub gateway doesn't exist yet

You create the spoke-to-hub peering with --use-remote-gateways true, but the VPN Gateway in the hub hasn't been provisioned yet (gateways take 30-45 minutes to provision). The peering fails with an error. The correct approach is to enable this option only after the gateway is completely provisioned and operational.

Not updating NSGs when creating peerings

Peering created between VNet-Frontend and VNet-Database. Administrators assume that now frontend VMs access the database. But the NSG on the database subnet only allows traffic from 10.0.2.0/24 (backend), not from 10.0.1.0/24 (frontend via peering). The peering exists, but the NSG blocks. Always review NSGs in both VNets when creating peerings.


11. Operation and Maintenance​

Monitor Status of All Peerings in a Subscription​

# List all peerings in all VNets of a subscription
$vnets = Get-AzVirtualNetwork
foreach ($vnet in $vnets) {
$peerings = Get-AzVirtualNetworkPeering `
-VirtualNetworkName $vnet.Name `
-ResourceGroupName $vnet.ResourceGroupName

foreach ($peering in $peerings) {
[PSCustomObject]@{
VNet = $vnet.Name
PeeringName = $peering.Name
Status = $peering.PeeringState
RemoteVNet = $peering.RemoteVirtualNetwork.Id.Split('/')[-1]
ForwardedTraffic = $peering.AllowForwardedTraffic
GatewayTransit = $peering.AllowGatewayTransit
UseRemoteGateways = $peering.UseRemoteGateways
}
}
} | Format-Table -AutoSize

Check Effective Routes to Confirm Active Peering​

# Check effective routes of a specific NIC
az network nic show-effective-route-table \
--name nic-vm-frontend \
--resource-group rg-producao \
--output table

Entries with nextHopType: VNetPeering confirm that peering is active and routes have been propagated.

Connectivity Diagnosis via Network Watcher​

# Test connectivity between two VMs (requires Network Watcher enabled)
az network watcher test-connectivity \
--source-resource /subscriptions/<sub-id>/resourceGroups/rg-producao/providers/Microsoft.Compute/virtualMachines/vm-frontend \
--dest-resource /subscriptions/<sub-id>/resourceGroups/rg-dev/providers/Microsoft.Compute/virtualMachines/vm-dev \
--protocol TCP \
--dest-port 80

The result shows if the connection was successful, and in case of failure, where in the path the blocking occurred (NSG, route, etc.).

Important Limits​

ItemDefault limit
Peerings per VNet500
VNets in chain for Gateway Transit1 (cannot chain: Spoke1-Hub1-Hub2-OnPrem)
Transfer cost via peeringCharged per GB transferred (varies by region and direction)
Peering bandwidthLimited by VM NIC bandwidth, not by peering

The limit of 500 peerings per VNet is rarely reached in traditional hub-spoke architectures, but in very large enterprise environments with Azure Virtual WAN it can be relevant.


12. Integration and Automation​

VNet Peering in Infrastructure Pipelines​

In infrastructure CI/CD pipelines (Azure DevOps, GitHub Actions), creating peerings should be part of the new VNet provisioning process. A new environment (e.g., new production region) should automatically create:

  1. The new VNet
  2. Peerings to the Hub
  3. Reverse peerings from Hub to the new VNet
  4. Necessary UDRs for routing

Terraform example for creating bidirectional peerings:

# Peering from Hub to Spoke
resource "azurerm_virtual_network_peering" "hub_to_spoke" {
name = "peering-hub-to-${var.spoke_name}"
resource_group_name = var.hub_rg
virtual_network_name = var.hub_vnet_name
remote_virtual_network_id = azurerm_virtual_network.spoke.id

allow_forwarded_traffic = true
allow_gateway_transit = true
allow_virtual_network_access = true
}

# Peering from Spoke to Hub
resource "azurerm_virtual_network_peering" "spoke_to_hub" {
name = "peering-${var.spoke_name}-to-hub"
resource_group_name = var.spoke_rg
virtual_network_name = azurerm_virtual_network.spoke.name
remote_virtual_network_id = var.hub_vnet_id

allow_forwarded_traffic = true
use_remote_gateways = var.use_remote_gateway
allow_virtual_network_access = true

depends_on = [azurerm_virtual_network_peering.hub_to_spoke]
}

Azure Virtual WAN: Managed Alternative for Connectivity at Scale​

For organizations with dozens or hundreds of VNets and multiple on-premises connections, Azure Virtual WAN solves the transitivity problem in a managed way:

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

In Virtual WAN, transitive connectivity is native: Spoke1 can talk to Spoke2 without additional NVA or UDRs. Microsoft manages the routing internally.


13. Final Summary​

Essential points:

  • A VNet Peering is always two objects (one in each VNet). Both need to exist and be in Connected state for traffic to flow.
  • Peering is non-transitive: A peered with B, B peered with C, doesn't mean A communicates with C.
  • Two types: Local VNet Peering (same region) and Global VNet Peering (different regions). Both use Microsoft's private backbone network.
  • Address spaces of peered VNets cannot overlap.
  • NSGs continue to apply after peering. Peering connects the networks; NSGs control traffic.

Critical differences:

  • "Connected" state vs. "Initiated": Connected means both sides exist and communication works. Initiated means only one side was created; no communication.
  • Allow forwarded traffic vs. Allow gateway transit: the first allows traffic forwarded by an NVA to pass through peering; the second allows the other VNet to use this VNet's gateway.
  • Peering vs. VPN Gateway: peering is direct, no hardware, uses private backbone, no additional encryption. VPN uses gateway, has gateway hourly cost, more suitable for on-premises.
  • Local peering vs. Global peering: slightly different latency; global peering has higher transfer cost and some limitations with Basic Load Balancer.

What needs to be remembered:

  • When adding address space to a VNet that has peerings, it's necessary to synchronize the peerings to propagate new routes.
  • For hub-spoke with gateway in hub: Allow gateway transit on hub peering + Use remote gateways on spoke peering. Gateway must be provisioned before enabling "Use remote gateways".
  • Peering between subscriptions requires Network Contributor permissions on both VNets, in their respective subscriptions.
  • Limit is 500 peerings per VNet. In very large environments, consider Azure Virtual WAN.
  • The combination peering + UDRs + NSGs forms the basis of network segmentation in Azure. Peering provides connectivity; UDRs control routing; NSGs control allowed traffic.