1. **Hub-spoke.** One hub VNet holds the private DNS zones (`privatelink.blob.core.windows.net`, `privatelink.vaultcore.azure.net`, `privatelink.servicebus.windows.net`, ...). Spoke VNets link to the zones (virtual network links). Zones are cheap; one per service type, shared across spokes.
2. **Create endpoints in the spoke**, in the private-endpoint subnet. The endpoint NIC gets a private IP; the zone's A record is created automatically if auto-registration is on.
3. **Verify resolution FROM the workload.** From the App Service console / pod / VM in the spoke: `nslookup [account].blob.core.windows.net` must return the private IP (10.x). Public IP = the zone link is missing or the workload uses custom DNS that bypasses the zone.
4. **Custom DNS.** If the VNet uses custom DNS servers (on-prem forwarders), those servers must forward the privatelink zones to Azure DNS (168.63.129.16). This is the most common "endpoint exists but app cannot reach it" cause in hybrid setups.
5. **Then lock down.** Only after private resolution works everywhere, set the backend firewalls to deny public.
Traps:
- Zone linked to the hub but the workload is in an unlinked spoke.
- Two zones for the same service (one per spoke) with conflicting records.
- Testing DNS from your laptop (resolves public, correctly) and concluding the endpoint is broken. Test from inside.
Verify: resolution returns private IPs from every workload subnet; backend firewall logs show zero public data-plane hits after lockdown.