Serverless VNet Integration in Azure
Serverless functions and App Service apps are easy to deploy, but they run outside your VNet by default. When they need to call your internal database, hit a private API, or access storage through a private endpoint, they cannot — they are on Azure’s public infrastructure, not inside your network. VNet integration changes that.
What VNet integration does
VNet integration connects an App Service or Azure Functions app to a subnet in your VNet. This gives the app outbound access to resources inside the VNet — private databases, storage accounts with private endpoints, internal APIs, and on-premises resources via VPN or ExpressRoute.
Important: VNet integration is one-directional for outbound traffic. It lets the app call resources inside the VNet. It does not prevent the app from being reached via its public URL, and it does not give the app a private IP. For inbound private access to the app, you need a separate Private Endpoint on the app itself.
Regional VNet integration
Regional VNet integration is the modern, recommended approach. It works by delegating a subnet to the App Service or Functions plan. Azure injects virtual network interfaces into that subnet on behalf of the app when it makes outbound calls.
Requirements for regional VNet integration:
- The VNet must be in the same region as the App Service plan.
- A dedicated subnet for the integration. The subnet cannot be shared with VMs or other resources.
- Minimum subnet size: /28 (11 usable IPs). Recommended: /26 or larger for scale sets and multiple apps.
- The subnet must be delegated to Microsoft.Web/serverFarms.
Setting up VNet integration with the CLI
Create a dedicated subnet for VNet integration and delegate it to App Service:
# Create the integration subnet
az network vnet subnet create \
--name snet-appservice-integration \
--resource-group rg-prod-networking \
--vnet-name vnet-prod-eastus-001 \
--address-prefixes 10.0.10.0/26 \
--delegations Microsoft.Web/serverFarmsCreate an App Service plan (Premium P1v3 for VNet integration support):
az appservice plan create \
--name asp-prod-premium \
--resource-group rg-prod-apps \
--location eastus \
--sku P1v3 \
--is-linuxCreate a function app on the premium plan:
az functionapp create \
--name func-backend-prod \
--resource-group rg-prod-apps \
--plan asp-prod-premium \
--storage-account mystorageaccountprod \
--runtime python \
--runtime-version 3.11 \
--os-type LinuxEnable VNet integration for the function app:
az functionapp vnet-integration add \
--name func-backend-prod \
--resource-group rg-prod-apps \
--vnet vnet-prod-eastus-001 \
--subnet snet-appservice-integrationVerify the integration is active:
az functionapp vnet-integration list \
--name func-backend-prod \
--resource-group rg-prod-appsRouting all outbound traffic through the VNet
By default, VNet integration only routes traffic destined for private IP ranges through the VNet. Public internet traffic from the app still goes out directly. To force all outbound traffic (including internet traffic) through the VNet — for example, to route it through Azure Firewall — enable the WEBSITE_VNET_ROUTE_ALL setting:
az functionapp config appsettings set \
--name func-backend-prod \
--resource-group rg-prod-apps \
--settings WEBSITE_VNET_ROUTE_ALL=1With this setting enabled, all outbound traffic from the function app routes through the integration subnet. If you have a route table on that subnet pointing to Azure Firewall, the firewall can inspect and control the function app’s internet traffic.
When WEBSITE_VNET_ROUTE_ALL=1 is enabled, the app needs a way to reach the internet through the VNet — either a NAT Gateway on the integration subnet or Azure Firewall in the hub. Without an outbound internet path, the app will lose internet connectivity entirely.
Private DNS resolution for serverless apps
When a function app calls a storage account with a private endpoint, DNS must resolve the storage hostname to the private IP. By default, VNet-integrated apps use Azure’s public DNS, which returns the public IP. Configure the app to use Azure Private DNS by setting the DNS server:
# Point the app to Azure's private DNS resolver (168.63.129.16 via VNet)
az functionapp config appsettings set \
--name func-backend-prod \
--resource-group rg-prod-apps \
--settings WEBSITE_DNS_SERVER=168.63.129.16168.63.129.16 is Azure’s internal DNS resolver. When the app queries it through the VNet integration, it uses the VNet’s DNS configuration, which includes Private DNS zone resolution.
Private inbound access to the app
VNet integration handles outbound access. For private inbound access (preventing the app from being reached via its public URL), create a Private Endpoint on the app:
# Get the app's resource ID
APP_ID=$(az functionapp show \
--name func-backend-prod \
--resource-group rg-prod-apps \
--query id \
--output tsv)
# Create a private endpoint for the function app
az network private-endpoint create \
--name pe-func-backend \
--resource-group rg-prod-networking \
--vnet-name vnet-prod-eastus-001 \
--subnet snet-privateendpoints \
--private-connection-resource-id $APP_ID \
--group-id sites \
--connection-name conn-func-backendAfter adding a private endpoint, disable public access on the app:
az functionapp update \
--name func-backend-prod \
--resource-group rg-prod-apps \
--set publicNetworkAccess=DisabledCommon mistakes
- Sharing the integration subnet with other resources. The integration subnet must be delegated to App Service and cannot contain VMs, private endpoints, or other resources. Attempting to place a VM in the integration subnet will fail. Create a dedicated subnet sized appropriately for the number of app instances.
- Not configuring DNS when calling private endpoints. The most common symptom is a connection timeout when calling a storage account or database via its private endpoint. The function app has network connectivity through VNet integration, but DNS returns the public IP. Set
WEBSITE_DNS_SERVER=168.63.129.16to enable private DNS resolution through the VNet. - Using Consumption plan and expecting VNet integration. Consumption plan Azure Functions scale to zero on shared infrastructure and do not support VNet integration. If you need VNet integration with scale-to-zero, use Premium Elastic plan or Azure Container Apps with serverless scaling enabled.
Summary
- VNet integration lets App Service and Azure Functions make outbound calls to resources inside your VNet — private databases, storage, internal APIs.
- It requires a dedicated subnet delegated to
Microsoft.Web/serverFarmsand a Premium-tier App Service plan. - Set
WEBSITE_VNET_ROUTE_ALL=1to route all outbound traffic through the VNet, enabling firewall inspection. - Set
WEBSITE_DNS_SERVER=168.63.129.16to use private DNS zones for private endpoint hostname resolution. - VNet integration only handles outbound traffic — add a Private Endpoint on the app itself for private inbound access.
Frequently asked questions
Does VNet integration give the function app a private IP inside the VNet?
Not exactly. VNet integration allows the function app to make outbound calls to resources in the VNet, but the function app itself does not get a private IP in the VNet. Inbound traffic to the function app still uses its public URL. For private inbound access, use Private Endpoints on the function app itself.
What is the difference between regional VNet integration and gateway-required VNet integration?
Regional VNet integration uses a dedicated subnet in the same region and does not require a VPN gateway. It is faster, lower latency, and the recommended approach for new deployments. Gateway-required integration is an older method for connecting to VNets in other regions.
Does VNet integration work with consumption plan Azure Functions?
Regional VNet integration requires at minimum a Premium plan for Azure Functions or a Basic plan for App Service. Consumption plan functions do not support VNet integration. Consider upgrading to Premium plan or using Azure Container Apps if you need VNet integration with serverless scale-to-zero.