Power Platform VNet Injection: The Primary/Secondary Myth

· 9 min read

By Juan Pedro Márquez

In a Power Platform VNet injection setup, "primary" and "secondary" don't route anything. They're declarative labels on the Enterprise Policy — not a routing directive. Traffic flows to wherever Microsoft has physically placed your environment, which you confirm with `Get-EnvironmentRegion`, not by reading the label. Get this wrong and you rebuild. It's the single most expensive misconception I see on these projects, and it hides in plain sight. A team reads "primary VNet = West Europe" as an instruction, provisions that VNet larger, concentrates capacity there — and then Microsoft places the environment in the paired region, so traffic flows through the "secondary" VNet they under-provisioned. Performance degrades, or connections fail. Now you're rebuilding the Enterprise Policy binding, which is disruptive and slow. On a recent working session with a European transport operator's platform team, catching this before they committed their IP plan collapsed a 33-VNet design into a lean two-VNets-per-environment model. Weeks of rebuild avoided, in one screen-share of `Get-EnvironmentRegion` output. This is the guide I wish they'd had going in. ## Do the "primary" and "secondary" labels route traffic? No. In a Power Platform [Enterprise Policy](https://learn.microsoft.com/en-us/power-platform/admin/vnet-support-overview) the "primary" and "secondary" VNet designations are declarative metadata. They do not select the path and they do not force traffic through a region. The [Europe geography, for example, spans two Azure regions](https://learn.microsoft.com/en-us/power-platform/admin/vnet-support-overview) (West Europe and North Europe), and Microsoft decides which one a given environment physically lives in. You can't pin placement. You can only declare a VNet pair that covers both regions. The one command that ends the argument is `Get-EnvironmentRegion`. It returns where the environment actually is. Declaring "primary = West Europe" while the environment sits in North Europe changes nothing about the traffic path — it just gives everyone a false sense of control. Verify placement; don't infer it from a label. ## Which Azure regions does your geography use? Because you can't pin placement, the design has to cover every region your Power Platform geography spans. Some geographies map to a single Azure region; the larger ones map to a pair, and you must have a delegated VNet in each. Check the [official list of supported regions](https://learn.microsoft.com/en-us/power-platform/admin/vnet-support-overview) before you draw a single subnet — the mapping is the input to your whole IP plan. | Power Platform geography | Azure regions (illustrative) | VNets required | |---|---|---| | Europe | West Europe + North Europe | 2 (one per region) | | United States | East US + West US | 2 (one per region) | | Single-region geographies | one region | 1 | The pattern to internalise: **two or more supported regions means two VNets, and it applies to non-production environments too** — not just production. Teams routinely plan the pair for prod and a single VNet for dev, then hit a wall when the dev Enterprise Policy won't create. ## What does VNet-injection failover actually need? Because you can't pin the region, the whole design has to assume Microsoft may place the environment on either side. That means both VNets must be first-class, not a big primary and a token secondary. ![What VNet-injection failover actually needs](https://hxpwtqrwvrlzxdcrcwbv.supabase.co/storage/v1/object/public/blog-images/posts/power-platform-vnet-injection-primary-secondary-myth-needs.webp) - **Two VNets in paired regions.** For any geography with two or more supported regions, you need a VNet in each — and it applies to non-production environments too. - **Equal-size, adequately sized subnets.** Both delegated subnets must have the same number of IP addresses, and Microsoft's guidance is /24, not the /27 many teams reach for. See [subnet delegation](https://learn.microsoft.com/en-us/azure/virtual-network/subnet-delegation-overview). - **[Peering between the two VNets](https://learn.microsoft.com/en-us/azure/virtual-network/virtual-network-peering-overview).** Failover only works if the pair can talk to each other. - **[Private DNS Zones linked to both](https://learn.microsoft.com/en-us/azure/dns/private-dns-overview) VNets** — not just the one you called "primary". - **Verified placement.** Run `Get-EnvironmentRegion` on the actual environment before you finalise capacity. Miss any one of these and failover silently doesn't work — which you discover at the worst possible moment. ## Setting it up: the PowerShell path The whole flow lives in the `Microsoft.PowerPlatform.EnterprisePolicies` module, and it's short once the design is right. Install and import it first: ```powershell Install-Module Microsoft.PowerPlatform.EnterprisePolicies Import-Module Microsoft.PowerPlatform.EnterprisePolicies ``` Delegate a subnet to Power Platform in **each** region. Run this once per VNet in the pair: ```powershell New-VnetForSubnetDelegation ` -SubscriptionId "" ` -VirtualNetworkName "vnet-pp-dev-we" ` -SubnetName "snet-powerplatform" ``` Then create one Enterprise Policy that binds **both** VNets — this is the two-region form, and it's the step where teams wrongly think they're choosing a "primary": ```powershell New-SubnetInjectionEnterprisePolicy ` -SubscriptionId "" -ResourceGroupName "rg-pp-dev" ` -PolicyName "ep-pp-dev" -PolicyLocation "europe" ` -VirtualNetworkId "" -SubnetName "snet-powerplatform" ` -VirtualNetworkId2 "" -SubnetName2 "snet-powerplatform" ` -TenantId "" ``` The two VNets here are peers, not a hierarchy. After you link the policy to the environment (see the [setup and configure guide](https://learn.microsoft.com/en-us/power-platform/admin/vnet-support-setup-configure) for the exact linking command and the read-access grant it requires), confirm reality with `Get-EnvironmentRegion` and design against what it returns. Full parameter reference is in the [`New-SubnetInjectionEnterprisePolicy` docs](https://learn.microsoft.com/en-us/powershell/module/microsoft.powerplatform.enterprisepolicies/new-subnetinjectionenterprisepolicy). ## How big should the delegated subnets be? Bigger than you think, and equal on both sides. Microsoft's recommendation is /24 per delegated subnet. Teams routinely propose /27 to "save address space", then the environment scales, the subnet exhausts its IPs, and there's no clean fix — because once a subnet is delegated, changing its range requires a call to Microsoft Support and, in practice, a rebuild of the Enterprise Policy binding. A subnet also can't be reused across multiple Enterprise Policies — it's one delegated subnet per policy. The cost of over-sizing a subnet is a few hundred wasted private IPs. The cost of under-sizing one is a rebuild under pressure. That asymmetry should decide the number every time. ## The architecture that actually scales The instinct on a large tenant is one VNet per app, or per business unit — and that's how you end up with a plan of 30-plus VNets that nobody can operate. The pattern that holds up is enterprise hub-and-spoke with a **VNet pair per Azure environment**, not per app. Give each environment its own pair, addressed cleanly so the plan reads at a glance: | Environment | Region A VNet | Region B VNet | Delegated subnet | |---|---|---|---| | Dev | `10.10.0.0/16` | `10.11.0.0/16` | `/24` in each | | Test | `10.20.0.0/16` | `10.21.0.0/16` | `/24` in each | | Production | `10.30.0.0/16` | `10.31.0.0/16` | `/24` in each | Isolation comes from the environment boundary, not from multiplying VNets. That per-environment discipline is the same one behind [Copilot Studio ALM](/blog/copilot-studio-alm-pipelines-environments-solutions) — environments are the unit of separation, and everything else hangs off them. That's exactly the move that turned a 33-VNet proposal into two VNets, sixteen subnets, and eight Enterprise Policies — same isolation, a fraction of the operational surface. Set it up once with the [PowerShell configuration flow](https://learn.microsoft.com/en-us/power-platform/admin/vnet-support-setup-configure) and it's boring to run, which is the goal.

Free — VNet Injection Field Card

The one-page reference behind this article: the failover checklist, the three misconceptions that cost a rebuild, and the IP-plan rules to lock down before you delegate a single subnet.

Get the Field Card →
## How to tell your VNet injection is misconfigured Most broken setups fail in one of three ways, and each maps back to a lever above: - **Intermittent latency or timeouts that "move" between environments.** Classic sign that traffic is landing in the under-provisioned VNet because capacity was concentrated in the declared "primary". Fix: equal-capacity pairs, and stop trusting the label. - **Connections fail outright after a placement change.** Usually a missing peering between the two VNets, or Private DNS Zones linked to only one of them. Failover has no path. Fix: peer both VNets and link the DNS zones to both. - **The environment stops provisioning resources as it grows.** The delegated subnet has exhausted its IPs — the /27 tax. Fix: there's no in-place resize; plan for /24 up front and rebuild if you're already stuck. The through-line: none of these show up in the demo environment. They surface under production load, or the first time Microsoft moves your placement — which is exactly why the design has to be right before you commit the IP plan. ## The plan before you commit your IP plan 1. **Confirm the geography's regions.** Check how many Azure regions your Power Platform geography uses. Two or more means you need a VNet pair. 2. **Size for /24, equal on both sides.** Plan capacity for growth now — resizing later means Support and a rebuild. 3. **Peer the two VNets and link Private DNS Zones to both.** Do this before you create the Enterprise Policy, not after. 4. **Create one Enterprise Policy per environment pair**, then bind it to the environment. 5. **Run `Get-EnvironmentRegion`** and design against the real placement — never against the label. Do it in that order and the words "primary" and "secondary" become what they always were: labels, not architecture. ## Frequently asked questions ### Does the "primary" VNet in a Power Platform Enterprise Policy carry the traffic? No. "Primary" and "secondary" are declarative labels on the Enterprise Policy; they don't route traffic or select a region. Microsoft physically places the environment in one of the geography's Azure regions, and you confirm the actual region with `Get-EnvironmentRegion`. Design both VNets as equals. ### What subnet size does Power Platform VNet injection need? Microsoft's guidance is /24 per delegated subnet, and both subnets in a pair must have the same number of IP addresses. Avoid /27 — it exhausts under load, and once a subnet is delegated you can't resize it without contacting Microsoft Support and effectively rebuilding the Enterprise Policy binding. ### Why does failover fail even though I declared a secondary VNet? Because declaring a secondary isn't enough. Failover needs the two VNets peered with each other and the Private DNS Zones linked to both — not just the "primary". If either is missing, traffic to the region Microsoft placed you in has no working path. ### Do I need a VNet per app or per environment? Per environment. Enterprise hub-and-spoke with a VNet pair per Azure environment gives you isolation without exploding the VNet count. A VNet-per-app plan balloons into dozens of networks that are hard to operate; a pair-per-environment plan stays lean and scales. ### Can I reuse one delegated subnet across several Enterprise Policies? No. A delegated subnet maps to a single Enterprise Policy. If you have three environment pairs, you need three pairs of delegated subnets — which is another reason the per-environment model is cleaner than trying to share networks across environments.