Azure Virtual Network Manager for Disaster Recovery

Because ‘it won’t go down’ isn’t a DR strategy

When a regional outage hits—or someone trips over a network cable in the wrong data centre your we need to enact our Disaster Recovery plan. If you don’t have one, get one.

AVNM doesn’t replace DR, but it can sure make it more resilient and repeatable.

This post explores how to design AVNM with disaster recovery in mind, covering regional network segmentation, active/passive VNets, and failover patterns that actually hold up under pressure.

What is Disaster Recovery (DR) in the context of AVNM?

In Azure, Disaster Recovery planning means replicating your workloads and network configurations across regions to maintain availability during outages. AVNM helps by centralising network topology and connectivity rules, allowing consistent failover designs across your environments.

AVNM doesn’t manage replication or data for that you need to look towards services like Azure Site Recovery or Azure Backup. But it is critical in:

  • Ensuring consistent network security rules across primary and secondary regions
  • Deploying connectivity rules (mesh, hub-spoke) as code
  • Reducing risk of drift between your recovery and production network topologies

In short: AVNM helps your failover network behave like your production network—without extra manual effort.

How It Works

AVNM lets you define network groups and configurations (connectivity and security rules) centrally. You can apply these across VNets within and across regions. AVNM’s strength in DR is its ability to:

  • Manage cross-region connectivity policies
  • Apply consistent NSGs and admin rules (via Security Admin Rules)
  • Integrate into CI/CD pipelines for automated, ring-fenced deployment

In disaster recovery, you typically:

  • Mirror your VNet topologies across regions
  • Use AVNM to apply the same connectivity/security configurations to both sides
  • Trigger failover and know that the secondary region behaves like production

Real-World Impact

Let’s say you run an internal app stack with:

  • Azure Firewall and monitoring in a shared services VNet
  • Web + API + SQL tiers split across VNets in a production region
  • A full mirror of the above in a failover region

Without AVNM:

  • You manage peering, security groups, and routing in both regions manually
  • Any deviations hurt when failover is needed

With AVNM:

  • You define once, apply to both
  • Your DR region becomes predictable, testable, and deployment-safe

Implementation Examples

Scenario: Active/Passive split across regions

You’ve got:

  • Primary in Australia East
  • Secondary in Australia Southeast

You’ve built matching VNets: prod-web, prod-api, prod-db in both regions. Traffic is normally served from the primary. Failover is DNS-based or routed via Azure Traffic Manager / Front Door.

AVNM Approach

  1. Create a network group that includes both regions’ VNets
  2. Set up a hub-and-spoke security config for each region
  3. Apply the same configuration to both sets via AVNM
  4. Use Policy/Tags to enforce DR region VNets are always included
  5. (Advanced) Integrate with an automation pipeline to validate drift and deploy config updates

Azure Portal Steps

  1. Go to AVNM in Portal

  2. Create or select a Network Group

  3. Use dynamic membership rules—example:

    1
    2
    3
    
    tag.region = australiaeast
    or
    tag.region = australiasoutheast
    
  4. Define a Connectivity Configuration:

    • Topology: Hub and Spoke
    • Assign matching Hubs per region
    • Add all VNets using dynamic rules
  5. Define a Security Admin Rule Collection:

    • Allow: L3 inbound between Trusted VNets (e.g., API -> DB)
    • Deny: Internet inbound except Web zone

Bicep Example

In this example we are deploying two Virtual Networks in each Australia region connecting them using a Hub-n-Spoke topology and then applying security rules. Note that the example is missing the deployment scripts to deploy the configurations but you can get that from my previous posts.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
@description('Location for all resources')
param location string = resourceGroup().location

@description('Configuration type to deploy')
param configType string = 'Connectivity'

// Create AU East Hub VNet
resource auEasthubVnet 'Microsoft.Network/virtualNetworks@2024-07-01' = {
  name: 'MyHubVNet-AUEast'
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }
  }
  tags: {
    environment: 'HubNet'
    region: 'australiaeast'
  }
}

// Create Spoke VNets
resource auEastspokeVnet01 'Microsoft.Network/virtualNetworks@2024-07-01' = {
  name: 'MySpokeVNet01-AUEast'
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.1.0.0/16'
      ]
    }
  }
  tags: {
    environment: 'production'
    region: 'australiaeast'
  }
}

// Create AU Southeast Hub VNet
resource auSoutheastHubVnet 'Microsoft.Network/virtualNetworks@2024-07-01' = {
  name: 'MyHubVNet-AUSouth'
  location: 'australiasoutheast'
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.10.0.0/16'
      ]
    }
  }
  tags: {
    environment: 'HubNet'
    region: 'australiasoutheast'
  }
}

// Create Spoke VNets
resource auSoutheastspokeVnet01 'Microsoft.Network/virtualNetworks@2024-07-01' = {
  name: 'MySpokeVNet01-AUSouth'
  location: 'australiasoutheast'
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.11.0.0/16'
      ]
    }
  }
  tags: {
    environment: 'production'
    region: 'australiasoutheast'
  }
}

// Create AVNM in each region
resource AUEastavnm 'Microsoft.Network/networkManagers@2024-07-01' = {
  name: 'mynetworkManager-AUEast'
  location: location
  properties: {
    networkManagerScopeAccesses: [
      configType
    ]
    networkManagerScopes: {
      subscriptions: [
        subscription().id
      ]
    }
  }
}

resource AUSouthavnm 'Microsoft.Network/networkManagers@2024-07-01' = {
  name: 'mynetworkManager-AUSouth'
  location: 'australiasoutheast'
  properties: {
    networkManagerScopeAccesses: [
      configType
    ]
    networkManagerScopes: {
      subscriptions: [
        subscription().id
      ]
    }
  }
}

// Create Network Groups
resource auEasthubGroup 'Microsoft.Network/networkManagers/networkGroups@2024-07-01' = {
  parent: AUEastavnm
  name: 'AUEast-HubGroup'
  properties: {
    description: 'AU East Hub VNet group'
  }
}

resource auSoutheasthubGroup 'Microsoft.Network/networkManagers/networkGroups@2024-07-01' = {
  parent: AUSouthavnm
  name: 'AUSouth-HubGroup'
  properties: {
    description: 'AU Southeast Hub VNet group'
  }
}

// Static Network Groups for Hubs
resource AUEastStaticNetworkGroupHub 'Microsoft.Network/networkManagers/networkGroups/staticMembers@2024-05-01' = {
  parent: auEasthubGroup
  name: 'AVNM-AUEast-HubGroup-Static'
  properties: {
    resourceId: auEasthubVnet.id
  }
}

resource AUSouthStaticNetworkGroupHub 'Microsoft.Network/networkManagers/networkGroups/staticMembers@2024-05-01' = {
  parent: auSoutheasthubGroup
  name: 'AVNM-AUSouth-HubGroup-Static'
  properties: {
    resourceId: auSoutheastHubVnet.id
  }
}

// Dynamic Network Groups for Spokes
resource auEastSpokeGroup 'Microsoft.Network/networkManagers/networkGroups@2024-07-01' = {
  parent: AUEastavnm
  name: 'AUEast-prod-vnets'
  properties: {
    description: 'Production VNets tagged environment=production & region=australiaeast'
    dynamicMembershipDefinition: {
      criteria: [
        {
          memberType: 'Microsoft.Network/virtualNetworks'
          field: 'tag.environment'
          operator: 'Equals'
          value: 'production'
        }
        {
          memberType: 'Microsoft.Network/virtualNetworks'
          field: 'tag.region'
          operator: 'Equals'
          value: 'australiaeast'
        }
      ]
    }
  }
}

// Dynamic Network Groups for Spokes
resource auSouthSpokeGroup 'Microsoft.Network/networkManagers/networkGroups@2024-07-01' = {
  parent: AUSouthavnm
  name: 'AUSouth-prod-vnets'
  properties: {
    description: 'Production VNets tagged environment=production & region=australiasoutheast'
    dynamicMembershipDefinition: {
      criteria: [
        {
          memberType: 'Microsoft.Network/virtualNetworks'
          field: 'tag.environment'
          operator: 'Equals'
          value: 'production'
        }
        {
          memberType: 'Microsoft.Network/virtualNetworks'
          field: 'tag.region'
          operator: 'Equals'
          value: 'australiasoutheast'
        }
      ]
    }
  }
}

// Create Azure Policy for dynamic network group
module avnmAUEastDynamicProductionNetworkGroup 'avnm-policy-networkgroup-aueast.bicep' = {
  scope: subscription()
  name: 'avnm-dynamic-production-aueast-network-group-policy'
  params: {
    networkManagerName: 'mynetworkManager-AUEast'
  }
  dependsOn: [
    auEasthubGroup
  ]
}

module avnmAUSouthDynamicProductionNetworkGroup 'avnm-policy-networkgroup-ausouth.bicep' = {
  scope: subscription()
  name: 'avnm-dynamic-production-ausouth-network-group-policy'
  params: {
    networkManagerName: 'mynetworkManager-AUSouth'
  }
  dependsOn: [
    auSoutheasthubGroup
  ]
}

// Connectivity Configuration (Hub-and-Spoke)
resource AUEastconnectivityConfig 'Microsoft.Network/networkManagers/connectivityConfigurations@2024-07-01' = {
  parent: AUEastavnm
  name: 'hubAndSpokeConfig'
  properties: {
    connectivityTopology: 'HubAndSpoke'
    hubs: [
      {
      resourceId: auEasthubVnet.id
      resourceType: 'Microsoft.Network/virtualNetworks'
      }
    ]
    appliesToGroups: [
      {
        groupConnectivity: 'None'
        networkGroupId: auEastSpokeGroup.id
        useHubGateway: 'True'
        isGlobal: 'False'
      }
    ]
    description: 'Hub-and-spoke connectivity'
  }
}

resource AUSouthconnectivityConfig 'Microsoft.Network/networkManagers/connectivityConfigurations@2024-07-01' = {
  parent: AUSouthavnm
  name: 'hubAndSpokeConfig'
  properties: {
    connectivityTopology: 'HubAndSpoke'
    hubs: [
      {
      resourceId: auSoutheastHubVnet.id
      resourceType: 'Microsoft.Network/virtualNetworks'
      }
    ]
    appliesToGroups: [
      {
        groupConnectivity: 'None'
        networkGroupId: auSouthSpokeGroup.id
        useHubGateway: 'True'
        isGlobal: 'False'
      }
    ]
    description: 'Hub-and-spoke connectivity'
  }
}

Gotchas & Edge Cases

  • Latency between regional hubs: Avoid cross-region mesh unless you’re really sure—firewall packet inspection adds rub.
  • Dynamic group membership: Based on tags or names—great until someone renames things.
  • NVA scenarios: Injected routes or third-party appliances must have mirrored configs too. AVNM won’t fix asymmetric routing hell.
  • Policy deployments: AVNM config changes can take minutes to fully propagate—be patient with failovers.

Best Practices

  • Align regional DR VNets with matching naming and tagging standards
  • Use dynamic network groups for easy inclusion of new VNets
  • Validate AVNM configuration in both regions as part of DR tests
  • Pair with Azure Policy to enforce required AVNM configuration
  • Version-control AVNM definitions via IaC (Bicep, Terraform)
🍺
Brewed Insight:

Too many DR setups assume “we’ll just replicate the app and connect stuff later”—but if your network isn’t aligned, failover equals facepalm. AVNM gets rid of tedious, error-prone per-region setups and gives you a DR network as predictable as a long black on Monday morning.

Don’t wait until the outage.

Learn More