Every Azure estate reaches the same week: someone asks why the storage account is reachable from the internet, the answer is "because that is the default", and the team sets out to fix it. Two days later there is a ticket titled "app can resolve the storage account but gets the public IP".
That ticket is the whole topic. The networking part of private endpoints is easy. The DNS part is where it goes wrong.
Service endpoints versus private endpoints
Service endpoints extend your VNet identity to the PaaS service over the Azure backbone and let the service's firewall allow traffic from a specific subnet. The service keeps its public IP and public DNS name. Traffic stays on the backbone, but the resource is still addressable from outside unless the firewall denies it.
Private endpoints give the service a private IP inside your VNet. The resource becomes reachable over that IP, public network access can be disabled completely, and the connection works from anywhere that can route to your VNet, including on-premises over ExpressRoute or VPN.
Service endpoints are free; private endpoints cost per hour plus data processed. For anything holding customer data, the private endpoint is the right answer and the cost is not the deciding factor. For a development storage account, a service endpoint with a firewall rule is proportionate.
The DNS problem, stated plainly
When you create a private endpoint, the public DNS name of the resource — mystorage.blob.core.windows.net — still resolves publicly to a public IP. What makes it resolve to the private IP is a private DNS zone (privatelink.blob.core.windows.net) linked to the VNet, containing an A record for the endpoint.
The failure modes follow directly:
- The zone exists but is not linked to the VNet doing the query. Resolution returns the public IP, the connection either fails or silently goes over the internet.
- Each team created their own zone. Now you have four
privatelink.database.windows.netzones with different records, and which one you get depends on which VNet you are in. This is the mess that takes a weekend to untangle. - On-premises clients cannot resolve it at all, because your corporate DNS knows nothing about Azure private zones.
The layout that works
One set of private DNS zones, in the connectivity subscription, linked to every VNet. Centralise them from the start. Create them with Terraform, and use Azure Policy (DeployIfNotExists) to automatically register every new private endpoint into the correct central zone. That policy is the single most valuable thing in this article: it means a team creating a private endpoint cannot get the DNS wrong, because they are not involved in it.
A DNS forwarder in the hub — either Azure Firewall's DNS proxy or Azure DNS Private Resolver — so on-premises clients forward Azure zone queries to it and get the private answers. Private Resolver is the purpose-built option and removes the need to run forwarder VMs.
Deny public network access by policy on storage accounts, SQL servers, Key Vaults and Cosmos accounts in your production management group, so the private endpoint is not merely present but is the only path.
Hub and spoke, and where the firewall goes
The standard shape: a hub VNet in the connectivity subscription with Azure Firewall, the VPN or ExpressRoute gateway, and the DNS resolver; spoke VNets per workload subscription, peered to the hub, with user-defined routes sending egress through the firewall.
Two decisions worth making deliberately:
- Azure Firewall or a network virtual appliance. Firewall is managed, integrates with policy, and is expensive at low volume. For a small estate, NSGs plus a NAT gateway may be proportionate — but you lose FQDN-based egress filtering, which is a real detection and exfiltration control.
- Virtual WAN or classic hub-and-spoke. Virtual WAN is worth it with many regions and branch sites; classic peering is simpler for a single-region estate.
Network security groups on every subnet, with flow logs enabled to a storage account and traffic analytics on. As with flow logs on AWS, the value shows up during an incident, and only if someone set it up beforehand.
The IP planning part
Non-overlapping address space across VNets, on-premises and any partner network, from a documented plan. Private endpoints consume an IP each, so size the endpoint subnet with room to grow — a /26 fills up faster than you expect in an estate with per-workload storage accounts and databases.
We deploy this alongside the management group and policy structure at the start of most cloud engagements, because the DNS policy has to exist before teams start creating endpoints, not after.
What to do this week
List your private DNS zones across all subscriptions. If there is more than one zone per service type, or if any zone is not linked to the VNets that query it, you have found the source of the next confusing outage.