A private endpoint gives an Azure PaaS service — a storage account, a SQL database, a Key Vault — a private IP address inside your VNet. The service becomes reachable over your private network instead of its public endpoint. The networking is the easy part. DNS is where teams get stuck, because the same hostname must now resolve differently depending on where the query comes from.
Here is the mental model.
The problem DNS has to solve
Your storage account is contoso.blob.core.windows.net. Publicly, that name resolves to a Microsoft-owned public IP. Once you add a private endpoint, a client inside your VNet must instead resolve it to the endpoint's private IP — while the public name stays unchanged. You cannot just override the public record globally; you need location-aware resolution.
Azure solves this with a CNAME indirection. contoso.blob.core.windows.net is a CNAME to contoso.privatelink.blob.core.windows.net. The privatelink zone is where the split happens.
The three pieces
- The private DNS zone — you create
privatelink.blob.core.windows.netas an Azure Private DNS zone and link it to the VNet. Inside that VNet, this zone is authoritative. - The A record — when the private endpoint is created, an A record for your account is registered in that zone, pointing at the endpoint's private IP. (Azure can do this automatically via the endpoint's DNS zone group — use it; manual records drift.)
- The resolution path — a client in the linked VNet queries the account name, follows the CNAME to the
privatelinkzone, hits the private A record, and gets the private IP. A client on the public internet follows the same CNAME but resolves theprivatelinkname via public DNS to the public IP.
See the official DNS integration guidance for the per-service zone names — they differ (privatelink.database.windows.net, privatelink.vaultcore.azure.net, and so on).
Where it breaks in hub-and-spoke
The classic failure: the private DNS zone is linked to the hub VNet, but clients live in a spoke, and the spoke's DNS points at a custom resolver (or a firewall) that doesn't forward to Azure-provided DNS (168.63.129.16). The spoke never reaches the zone, resolution falls through to public DNS, and traffic silently takes the public path — or fails if the public endpoint is locked down.
The fix is a deliberate DNS design: either link the zone to every VNet that needs it, or centralize resolution on a DNS resolver in the hub (Azure DNS Private Resolver) that all spokes forward to. Pick one and apply it everywhere — the failure mode of a half-applied design is the worst of both.
Common mistakes
- Manual A records instead of the DNS zone group — they don't update when the endpoint IP changes.
- Forgetting the CNAME chain — testing with
nslookupon theprivatelinkname directly and concluding it works, when the account name is what clients actually query. - One zone per subscription sprawl — you need one zone per service type per DNS scope, not one per resource.
If your private connectivity is brittle, this is usually why. It's a core part of our cloud networking and Azure Foundation work.