For a long time, DNS forwarder VMs were the standard answer for hybrid name resolution in Azure. Today they cause more work than they save. On new projects I now use Azure DNS Private Resolver by default, because there's nothing to patch, no failover to handle by hand, and it scales natively in Azure. Moving away from older VM-based DNS setups still raises a few questions in real environments, though. Where do the endpoints go, what does on-prem conditional forwarding to Private Link need, and where do teams usually get stuck? This guide is based on what I've seen in the field.
The resolver belongs in the hub VNet with two dedicated subnets
The recommendation here is clear. Deploy Azure DNS Private Resolver in your hub VNet rather than separately in each spoke. A central resolver is easier to manage and cheaper, particularly because every resolver needs two dedicated subnets: one for inbound endpoints, which accept queries from outside Azure such as your on-prem DNS servers, and one for outbound endpoints, which Azure resources use to forward queries to on-prem or external domains. Both subnets have to be delegated to 'Microsoft.Network/dnsResolvers' before deployment. If they aren't, setup fails with a cryptic error. The step itself is simple, but people miss it easily, especially when they're reworking existing infrastructure.
Practical tip: Set the subnet delegation to 'Microsoft.Network/dnsResolvers' before you create the resolver. In my experience, forgetting this is the #1 reason deployments fail.
Routing is the second trap. The resolver subnets need to be reachable from every spoke and from your on-premises networks (over VPN or ExpressRoute) so DNS queries can travel in both directions. If you take shortcuts here, you'll end up chasing odd DNS failures that are hard to track down.
The inbound endpoint takes on-prem conditional forwarding for Private Link
Plenty of organisations rely on conditional forwarders on their on-prem DNS servers to resolve Azure Private Link zones such as privatelink.database.windows.net. Before the resolver existed, that usually meant running several forwarder VMs, sometimes with clumsy NAT or incomplete routing. With Azure DNS Private Resolver you expose an inbound endpoint in the hub VNet, give it a private IP and use that IP as the target for your on-prem conditional forwarders.
The setup itself is quick. Create the inbound endpoint, assign the IP you want from the dedicated subnet, and point the forwarders for the Private Link zones on your on-prem DNS servers at it. The official documentation explains the basics. In actual deployments, firewall rules are where things tend to break: UDP/TCP 53 has to be open from the on-prem DNS servers to the endpoint. If it isn't, name resolution fails without any obvious error.
The outbound endpoint and a ruleset handle Azure-to-on-prem resolution
The opposite direction, Azure workloads resolving on-premises domains, runs through the outbound endpoint, which again sits in its own dedicated subnet. You attach a forwarding ruleset to it that defines which domains get forwarded (for example contoso.local) and which on-prem DNS servers receive them. Everything else resolves natively in Azure. You no longer have to maintain static DNS server settings on every VNet or keep awkward custom DNS VMs around. The documentation on endpoints and rulesets describes how it works, but in practice the routing and VNet associations are what decide whether it works.
The errors I run into most often are VNets that were never associated with the ruleset, missing routes from the spokes to the hub, and firewalls blocking traffic between Azure subnets and the on-prem DNS servers. A short connectivity test in Azure Network Watcher can save you hours of troubleshooting later.
One diagram shows the complete hybrid DNS flow
For planning or a migration, a simple diagram helps a lot. In this one, the on-prem DNS servers send Private Link zone queries to the inbound endpoint, and Azure VMs use the outbound endpoint to resolve on-prem domains through conditional forwarding.
flowchart LR
OnPrem["On-prem DNS server"] --> Inbound["Inbound endpoint (hub VNet)"]
Inbound --> AzurePrivateDNS["Private Link zone"]
AzureVM["Azure VM (spoke)"] --> Outbound["Outbound endpoint (hub VNet)"]
Outbound --> OnPrem
Figure: Azure DNS Private Resolver with inbound and outbound endpoints in a hub-spoke design.
Costs stay manageable, but a few pitfalls keep coming up
Teams often balk at the ongoing cost of Azure DNS Private Resolver. In practice it usually works out cheaper than running and maintaining a group of DNS VMs, particularly if you need high availability. You don't patch anything, you don't track an OS lifecycle, and Microsoft's SLA and support come with it. By far the most frequent mistakes I see are subnet delegation and routing. After that come missing network rules or VNet associations, which leave the endpoints unreachable from on-prem or from the spokes.
If you work with Private Endpoints, have a look at my post on DNS pitfalls with Azure Private Endpoints. Many of the technical traps are much the same.
Private Resolver is now my standard for DNS modernisation
Azure DNS Private Resolver has changed hybrid DNS in Azure without much fanfare. If you plan the subnet layout, the delegation and the routing from the start, you get reliable, enterprise-grade DNS for Azure and on-prem with little ongoing effort. The usual mistakes (missing delegation, broken routing, forgotten firewall ports) are easy to avoid with a checklist and some testing up front. On my new builds, Private Resolver is the default, and I don't know a better way to get rid of old DNS forwarder VMs for good.


