Internal Load Balancers in Azure
When you run multiple VMs to handle backend workload — application servers, API services, database read replicas — you need something to distribute traffic evenly between them and stop sending traffic to VMs that have gone offline. That is exactly what an internal load balancer does, and it does it entirely within your private network.
What an internal load balancer does
An Azure internal load balancer (ILB) has a private IP address from your VNet. Clients — whether VMs, applications, or on-premises systems — send traffic to that private IP. The load balancer picks one of the healthy backend VMs and forwards the traffic to it.
From the client’s perspective, there is one IP address and one endpoint. The load balancer is invisible. If a backend VM crashes, the load balancer stops routing to it within seconds (once health probes fail). The client notices only a brief pause, not a full outage.
Internal load balancers are used for:
- Application tier VMs fronted by web tier VMs in a multi-tier architecture.
- Database read replicas or read-only clusters.
- Internal microservices where one service calls another through a stable IP.
- SAP HANA and SQL Server Always On availability groups (which require a single IP for the listener).
Key components
Frontend IP configuration: The private IP address clients connect to. This IP comes from a subnet in your VNet.
Backend pool: The set of VMs that receive traffic. VMs are added by their NIC or IP configuration, not by name.
Health probe: A regular check the load balancer makes against each backend VM. If a VM fails the probe, the load balancer stops sending it traffic. Health probes can check HTTP, HTTPS, or TCP ports.
Load balancing rule: Maps a frontend IP and port to a backend pool and port. For example: frontend port 80 → backend pool → port 80.
Session persistence: Optionally sticks a client to the same backend VM. Options are None (default, best distribution), Client IP (same client always goes to same VM), or Client IP and Protocol.
Creating an internal load balancer with the CLI
This example creates an internal load balancer for an application tier running on port 8080:
# Create the Standard SKU internal load balancer with a frontend private IP
az network lb create \
--name lb-app-internal \
--resource-group rg-prod-compute \
--sku Standard \
--vnet-name vnet-prod-eastus-001 \
--subnet snet-app \
--frontend-ip-name fe-app \
--private-ip-address 10.0.2.10 \
--backend-pool-name be-app-servers
# Create the health probe (HTTP check on /health endpoint)
az network lb probe create \
--lb-name lb-app-internal \
--resource-group rg-prod-compute \
--name probe-http \
--protocol Http \
--port 8080 \
--path /health \
--interval 15 \
--threshold 2
# Create the load balancing rule
az network lb rule create \
--lb-name lb-app-internal \
--resource-group rg-prod-compute \
--name rule-app-8080 \
--protocol Tcp \
--frontend-port 8080 \
--backend-port 8080 \
--frontend-ip-name fe-app \
--backend-pool-name be-app-servers \
--probe-name probe-http \
--load-distribution Default \
--idle-timeout 4Add VMs to the backend pool:
# Add a VM's NIC to the backend pool
az network nic ip-config update \
--name ipconfig1 \
--nic-name vm-app-01VMNic \
--resource-group rg-prod-compute \
--lb-name lb-app-internal \
--lb-address-pools be-app-servers
az network nic ip-config update \
--name ipconfig1 \
--nic-name vm-app-02VMNic \
--resource-group rg-prod-compute \
--lb-name lb-app-internal \
--lb-address-pools be-app-serversCheck the health of the backend pool to see which VMs are passing health probes:
az network lb probe show \
--lb-name lb-app-internal \
--resource-group rg-prod-compute \
--name probe-httpHA ports: load balance all traffic
Standard SKU internal load balancers support HA (high availability) ports. Instead of specifying individual port rules, an HA port rule forwards all TCP and UDP traffic on all ports to the backend pool. This is commonly used with network virtual appliances (NVAs) where you want the load balancer to forward any protocol without knowing ports in advance.
az network lb rule create \
--lb-name lb-nva-internal \
--resource-group rg-prod-networking \
--name rule-ha-ports \
--protocol All \
--frontend-port 0 \
--backend-port 0 \
--frontend-ip-name fe-nva \
--backend-pool-name be-nva \
--probe-name probe-nvaHA ports are only supported on Standard SKU load balancers, not Basic. Use HA ports when fronting firewall appliances or other network devices that process arbitrary traffic.
Inbound NAT rules for direct VM access
Sometimes you need to reach individual VMs behind a load balancer directly — for SSH, RDP, or debugging. Inbound NAT rules map a specific port on the load balancer’s frontend IP to a specific VM’s port.
# Map frontend port 50001 to VM app-01 port 22 (SSH)
az network lb inbound-nat-rule create \
--lb-name lb-app-internal \
--resource-group rg-prod-compute \
--name nat-ssh-app01 \
--frontend-ip-name fe-app \
--protocol Tcp \
--frontend-port 50001 \
--backend-port 22
# Associate the NAT rule with the VM's NIC
az network nic ip-config update \
--name ipconfig1 \
--nic-name vm-app-01VMNic \
--resource-group rg-prod-compute \
--lb-inbound-nat-rules nat-ssh-app01 \
--lb-name lb-app-internalCommon mistakes
- Using TCP health probes instead of HTTP. A TCP probe only checks that the port is open. An HTTP probe checks that the application is actually responding correctly. A VM can accept TCP connections on port 8080 while the application is deadlocked and returning 500 errors. Use HTTP probes whenever the backend runs a web service.
- Putting the load balancer’s frontend IP in the same subnet as backends without NSG rules. The load balancer itself does not filter traffic, so NSG rules on the backend VMs must allow traffic from the load balancer’s frontend IP. The service tag
AzureLoadBalancercovers the load balancer’s health probe traffic, but you still need to allow port 8080 from the VNet source range. - Using Basic SKU in production. Basic SKU load balancers do not support availability zones, have limited SLAs, and are being retired. Always deploy Standard SKU for production workloads.
Summary
- An internal load balancer uses a private IP to distribute traffic between backend VMs entirely within your VNet — no public internet exposure.
- Health probes continuously check backend VMs and remove unhealthy instances from rotation automatically.
- Use HTTP health probes rather than TCP probes to detect application-level failures, not just network connectivity.
- HA port rules forward all TCP/UDP traffic to backends, useful for NVAs and firewall appliances.
- Always use Standard SKU for production load balancers to get zone redundancy and a supported product.
Frequently asked questions
What is the difference between an internal and an external load balancer?
An external (public) load balancer distributes internet traffic to VMs using a public IP address. An internal load balancer uses a private IP from your VNet and distributes traffic only from within your VNet, peered VNets, or connected on-premises networks.
Does an internal load balancer replace the need for NSGs?
No. The load balancer forwards traffic but does not filter it. NSGs on the backend VMs still control what traffic is allowed. Always keep NSG rules in place even with a load balancer in front of your VMs.
What happens when a health probe fails for all backend VMs?
If all backend VMs fail their health probes, the load balancer has no healthy backends. It will start responding to probes as if they are healthy and forward traffic anyway, to prevent total outage. This is called probe-down behavior. Your monitoring should alert before this happens.