Azure VNets follow most of the same CIDR rules as AWS VPCs, but with one major twist: some subnets have specific names that the platform recognizes and enforces sizes for. Pick the wrong name or size and the deployment fails — sometimes silently, sometimes with a clear error.

This article covers Azure's reserved subnet names, the correct size for each, the 5 reserved IPs per subnet, and how to lay out a production-grade VNet that supports VPN, Bastion, and Azure Firewall together.

Azure reserves 5 IPs per subnet

Like AWS, Azure reserves five addresses in every subnet:

AddressPurpose
.0Network address
.1Default gateway
.2 / .3Azure DNS mapping
lastBroadcast address

So a /29 (8 total addresses) gives you 3 usable, and a /24 gives 251 usable. Same arithmetic as AWS, different reserved purposes for two of the addresses.

Minimum subnet: /29

Unlike AWS (minimum /28), Azure allows subnets as small as /29. The portal will reject anything smaller. Practical minimum for production workloads is /27 or /26 — the /29 leaves only 3 usable addresses, which is too tight for almost anything except a single management appliance.

The named subnets that have size requirements

Subnet name (exact)Minimum sizeRecommendedPurpose
GatewaySubnet/29/27VPN/ExpressRoute gateway
AzureBastionSubnet/26/26Azure Bastion service
AzureFirewallSubnet/26/26Azure Firewall
AzureFirewallManagementSubnet/26/26Azure Firewall management traffic (basic SKU)
RouteServerSubnet/27/27Azure Route Server

The name match is exact and case-sensitive. GatewaySubnet is correct; Gateway-Subnet or gatewaysubnet is not — Azure will refuse to use it for the platform service.

GatewaySubnet

Used by the VPN gateway and ExpressRoute gateway. Microsoft documentation says minimum /29, but recommends /27 because it allows easier upgrades to higher-throughput gateway SKUs that need more addresses. There is no traffic in this subnet from your VMs — the gateway uses these addresses for its own ENIs and tunneling endpoints.

AzureBastionSubnet

Used by Azure Bastion (the managed jump host service). Must be /26 or larger. Cannot have an NSG attached in the basic SKU. Cannot be used for anything except Azure Bastion.

AzureFirewallSubnet

Used by Azure Firewall. Must be /26 or larger. Cannot be associated with an NSG (the firewall itself handles all traffic policy). For Premium SKU with TLS inspection, /25 or /24 may be needed depending on scale.

AzureFirewallManagementSubnet

Required only for the Basic SKU of Azure Firewall. Holds the firewall's management traffic separately. Also /26 minimum.

Standard production VNet layout

A typical hub-and-spoke layout in Azure, with all the named services:

10.0.0.0/16                          Hub VNet (65,531 usable)
+-- GatewaySubnet           10.0.0.0/27       (27 usable)
+-- AzureBastionSubnet      10.0.0.32/26      (59 usable)
+-- AzureFirewallSubnet     10.0.0.96/26      (59 usable)
+-- RouteServerSubnet       10.0.0.160/27     (27 usable)
+-- shared-services         10.0.1.0/24       (251 usable)
+-- (10.0.2.0 - 10.0.255.255 reserved)

10.1.0.0/16                          Spoke VNet 1 (workloads)
+-- web-tier                10.1.0.0/20       (4,091 usable)
+-- app-tier                10.1.16.0/20      (4,091 usable)
+-- db-tier                 10.1.32.0/24      (251 usable)
+-- (10.1.33.0 onward reserved)

VNet peering connects spokes to the hub. The hub provides shared services (firewall, VPN, DNS). Spokes do not peer with each other directly — traffic flows through the hub's firewall.

VNet peering and address overlap

Like AWS VPC peering, Azure VNet peering rejects overlapping address spaces. Plan CIDRs across all VNets the way you would across AWS VPCs — see our multi-cloud CIDR planning article.

Azure does allow some overlap if you do not need direct routing (e.g., if both VNets only reach an external service via the hub firewall), but the platform still warns you and the configuration is fragile.

Subnet expansion is supported

Unlike AWS (where subnet CIDRs are immutable after creation), Azure lets you expand a subnet's address range as long as the new range is still inside the VNet's address space and does not overlap other subnets. Shrinking is not supported.

This means you can start with a /27 and grow to a /24 later without recreating resources. Helpful for unpredictable workloads, though designing the right size up front is still better practice.

Common Azure subnet mistakes

  • Misspelling reserved names. Gatewaysubnet, azureBastionSubnet, AzureFirewall-Subnet — all rejected. Use exact casing.
  • Trying to attach NSGs to AzureBastionSubnet/AzureFirewallSubnet. Not allowed. The services manage their own traffic policy.
  • Sizing GatewaySubnet at /29. Technically allowed, but you cannot upgrade to high-performance gateway SKUs. Always start at /27.
  • Forgetting Azure reserves 5 IPs. Same trap as AWS. A /29 has 8 total but only 3 usable.
  • Not planning for managed service ENIs. Azure SQL, App Service, AKS pods, and Container Instances all consume ENIs from your subnets. Plan capacity accordingly.

AKS pod CIDR sizing

AKS supports two networking modes:

  • Kubenet: pods use an overlay range (default 10.244.0.0/16). Node count limited to 400.
  • Azure CNI: each pod gets a real VNet IP. Node count up to 5,000 but every pod consumes a VNet IP.

Azure CNI gives better performance and integration but burns VNet space. Plan the same way as EKS — see our Kubernetes CIDR sizing article for the full pattern. Azure CNI with dynamic IP allocation (Overlay mode, preview/GA in many regions) gives you EKS-prefix-delegation-style efficiency.

Terraform pattern for Azure

resource "azurerm_virtual_network" "hub" {
  name                = "hub-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = "eastus"
  resource_group_name = azurerm_resource_group.main.name
}

resource "azurerm_subnet" "gateway" {
  name                 = "GatewaySubnet"
  resource_group_name  = azurerm_resource_group.main.name
  virtual_network_name = azurerm_virtual_network.hub.name
  address_prefixes     = ["10.0.0.0/27"]
}

resource "azurerm_subnet" "bastion" {
  name                 = "AzureBastionSubnet"
  resource_group_name  = azurerm_resource_group.main.name
  virtual_network_name = azurerm_virtual_network.hub.name
  address_prefixes     = ["10.0.0.32/26"]
}

Our IaC Export tool generates this for Azure including the firewall, route server, and spoke peering setup.

Key takeaways

  • Azure VNets reserve 5 IPs per subnet (same count as AWS, different purposes).
  • Minimum subnet is /29. Practical minimum for workloads is /27.
  • Reserved subnet names are case-sensitive: GatewaySubnet, AzureBastionSubnet, AzureFirewallSubnet, AzureFirewallManagementSubnet, RouteServerSubnet.
  • Recommended size for GatewaySubnet is /27 (not the /29 minimum) to support gateway SKU upgrades.
  • Unlike AWS, Azure subnets can be expanded after creation.