CloudBrum
CloudBrum · Cloud decision-support platform
Azure Networking

Azure Load BalancerLast reviewedReading time~12 minLevelBeginner to advanced

Microsoft Azure · Networking · Layer 4 load balancer for TCP and UDP

Azure Load Balancer is the layer 4 balancer of Azure: it takes TCP and UDP connections that arrive at one address and hands each to a healthy server in a backend pool. It is fast, zone-aware and sits inside the Azure network, so it suits virtual machine scale sets, databases, game servers and the back half of a web tier. It doesn’t read HTTP, so web routing, TLS offload and a web firewall belong to Application Gateway or Front Door. The thing that catches most teams out is the other direction, outbound connections and the SNAT ports they use.

On this page (17 sections)

    Mind map: Azure Load Balancer at a glance

    Azure Load Balancer mind map Azure Load Balancer at a glance: SKUs and tiers: Standard, Gateway, Global (cross-region); Frontend: Public IP, Internal private IP, Zone-redundant or zonal; Backend: VMs and scale sets, IP-based pools, Cross-VNet backends; Rules: Load balancing rules, Inbound NAT rules, HA ports, floating IP; Health: TCP, HTTP, HTTPS probes, Probe threshold, Failure behaviour; Outbound: SNAT ports, NAT gateway, Outbound rules; Security: Closed by default, Network security groups, Private frontends; Pricing: Rules per hour, Data processed, Public IPs, NAT gateway. Azure Load Balancer at a glance Layer 4 load balancing on Azure: the main building blocks and decisions CloudBrum Cloud decision-support platform CloudBrum Standard Gateway Global (cross-region) SKUs and tiers Public IP Internal private IP Zone-redundant or zonal Frontend VMs and scale sets IP-based pools Cross-VNet backends Backend Load balancing rules Inbound NAT rules HA ports, floating IP Rules TCP, HTTP, HTTPS probes Probe threshold Failure behaviour Health SNAT ports NAT gateway Outbound rules Outbound Closed by default Network security groups Private frontends Security Rules per hour Data processed Public IPs, NAT gateway Pricing Load Balancer17-point analysis CloudBrum· 17-point cloud service analysis cloudbrum.com
    CloudBrum Load Balancer at a glance · 17-point analysis SKUs and tiers Standard Gateway Global (cross-region) Frontend Public IP Internal private IP Zone-redundant or zonal Backend VMs and scale sets IP-based pools Cross-VNet backends Rules Load balancing rules Inbound NAT rules HA ports, floating IP Health TCP, HTTP, HTTPS probes Probe threshold Failure behaviour Outbound SNAT ports NAT gateway Outbound rules Security Closed by default Network security groups Private frontends Pricing Rules per hour Data processed Public IPs, NAT gateway CloudBrum · cloudbrum.com

    Free to share. The downloaded image includes the CloudBrum link.

    Key features (summary)

    • Layer 4 distributionFor each new connection the load balancer hashes the source and destination address, the ports and the protocol, and picks a backend. All packets of that flow then go to the same server. Source IP persistence is available for clients that need to return to one server.
    • Health probesA TCP, HTTP or HTTPS probe tests each backend. After the set number of failures the server gets no new connections until the probe passes again. Existing connections keep going on a TCP flow unless the server resets them.
    • Public or internalA public load balancer fronts the internet with a public IP. An internal one has a private address inside the virtual network and balances between tiers, such as web to database.
    • Zone redundancyIn regions with availability zones, a Standard frontend can be zone-redundant and keep working if a zone fails, or pinned to one zone for placement control.
    • Outbound connectivityServers in the pool reach the internet through SNAT ports. Outbound rules and a NAT gateway give you control over which addresses and how many ports they get.
    • Rules and portsA rule maps a frontend port to a backend port. HA ports on an internal load balancer balance every port at once, and floating IP supports clustered databases. Inbound NAT rules reach one specific server.
    • Global tierA global load balancer has one anycast IP, and spreads TCP and UDP traffic across regional Standard load balancers in different regions, with failover between them.
    • Gateway Load BalancerChains third-party virtual appliances such as firewalls into the traffic path transparently, so the original source and destination are kept and the application needn’t change.

    Basic concepts

    Frontend IP configuration
    The address, public or private, that clients connect to. A load balancer can have several.
    Backend pool
    The set of network interfaces or IP addresses that receive the traffic. Virtual machines and scale set instances join it.
    Health probe
    A test that the load balancer runs against each backend, from the address 168.63.129.16. A backend that fails its probes receives no new connections.
    Load balancing rule
    Maps a frontend IP and port to a backend pool and port, with a probe, a distribution mode and an idle timeout.
    Session persistence
    Controls whether packets from the same client go to the same server: none (five-tuple hash), client IP, or client IP and protocol.
    Inbound NAT rule
    Forwards a frontend port to a single backend server and port, for example to reach one machine over SSH. These rules aren’t counted for billing.
    Outbound rule
    Defines which frontend addresses the backend uses for outbound connections and how many SNAT ports each server gets.
    SNAT and SNAT ports
    Source network address translation lets many private servers share a few public addresses. Each outbound connection to the same destination needs its own port, and the supply is limited.
    Standard and Basic SKU
    Standard is the production SKU, with zones, a service-level agreement and secure-by-default behaviour. The Basic SKU was retired on 30 September 2025.
    Gateway SKU
    A load balancer type used to insert virtual appliances in front of Standard frontends or network interfaces.
    Global tier
    A tier of Standard that spreads traffic across load balancers in several regions through one anycast address.
    HA ports
    An internal load balancer rule that balances all TCP and UDP ports, used for virtual appliances.
    TCP reset on idle
    An option that sends a reset to both ends when an idle connection times out, so applications learn about it at once instead of hanging.

    How to create & configure it

    Create a Standard load balancer for two web servers with the Azure CLI

    1. Check that layer 4 is what you needUse Azure Load Balancer for TCP and UDP traffic and for tiers inside a network. If you need URL routing, TLS offload or a WAF for web traffic, use Application Gateway or Front Door, and put this in front of other services.
    2. Plan the network and the security groupCreate the virtual network and the network security group first. A Standard load balancer blocks inbound traffic until a rule in the group allows it.
    3. Create a zone-redundant Standard public IPUse a Standard SKU public IP with all three zones, so the frontend survives a zone failure.
    4. Create the load balancer, a front end and a poolKeep names clear, since probes, rules and pools reference each other by name.
    5. Add a health probeUse HTTP against a real path such as /health. A TCP probe only shows that the port is open, not that the application works.
    6. Add the ruleMap the front end port to the back end port, attach the probe, set the idle timeout and turn on TCP reset.
    7. Plan outbound trafficAdd a NAT gateway to the subnet or define outbound rules, so servers don’t rely on the limited default SNAT ports.
    8. Add the servers to the poolCreate network interfaces that join the pool, then attach virtual machines, or point a scale set at the pool.
    9. Check the metricsDipAvailability shows the probe result per server, and VipAvailability shows whether the front end answers. Watch SNAT port use as well.

    Tip: Microsoft is moving new virtual networks to private subnets, which have no default outbound access, so servers behind a load balancer need an explicit way out: a NAT gateway, an outbound rule or a public IP of their own. Decide this at design time, since a missing outbound path shows up as updates and package downloads that hang. See the code references for the same setup as Terraform.

    Common issues after configuration

    SymptomLikely causeWhat to check / fix
    The front end doesn’t answer after creationA Standard load balancer is closed to inbound traffic by default: no security group rule allows it, the NICs aren’t in the pool, or the server’s own firewall blocks the portAdd an inbound allow rule to the network security group, confirm pool membership, and check the operating system firewall.
    Every backend is marked unhealthyThe probe port or path is wrong, the application isn’t listening, or a firewall or a deny rule blocks the probe source 168.63.129.16Test the probe path on the server, and allow the AzureLoadBalancer service tag in the network security group and the OS firewall.
    A server behind an internal load balancer can’t reach the front endA backend server can’t use its own internal load balancer’s frontend address, because the flow returns to the same machineUse a different tier or a separate client machine for the call, or a different front end design such as DNS to the servers.
    Outbound connections fail now and thenSNAT ports ran out: many connections to the same destination use up the ports available to each serverAdd a NAT gateway or an outbound rule with more addresses, reuse connections, and watch the SNAT metrics.
    Long-lived connections are cut after a few minutesThe default idle timeout is 4 minutes, and idle flows are droppedSend keep-alives, raise the idle timeout on the rule (up to 100 minutes on Standard) and turn on TCP reset.
    Traffic is uneven across serversThe five-tuple hash spreads connections, not load, so a few heavy or long-lived connections or a small number of clients skew itSpread clients, shorten connections where you can, or use client IP persistence only when you need it.
    A Basic load balancer stopped working or can’t be changedThe Basic SKU was retired on 30 September 2025Upgrade to Standard with Microsoft’s migration tooling, and use Standard public IPs.
    SKU mismatch when attaching a public IPA Standard load balancer needs Standard SKU public IPs, and Basic ones don’t mixCreate the public IP as Standard and static.
    Probes flap between healthy and unhealthyThe interval is short, the threshold is low, or the application is slow under loadRaise the threshold and the interval a little, and make the probe path cheap and independent of slow dependencies.
    Updates and downloads hang on new serversNo outbound path exists, because default outbound access isn’t available in the subnetAttach a NAT gateway to the subnet, add an outbound rule, or give the servers a public IP.
    The bill is higher than expectedMore rules than you need, a lot of data processed, public IPs and a NAT gateway that each cost separatelyMerge rules, delete unused load balancers and IPs, and review data processed per load balancer.

    Use cases: when and where to use it

    Good fit

    • TCP or UDP services that need to be spread across several servers
    • The internal tier of an application, such as web servers calling a database cluster
    • Virtual machine scale sets that need a stable front end
    • Chaining firewalls and other virtual appliances into traffic (Gateway Load Balancer)
    • Services that need fast, zone-aware balancing without a proxy in the middle
    • Spreading TCP or UDP traffic across regions with one anycast IP (global tier)

    Consider something else

    • HTTP(S) routing, TLS offload and a WAF inside a region → Azure Application Gateway
    • A global HTTP(S) entry point with caching and WAF → Azure Front Door
    • DNS-based routing for any protocol → Azure Traffic Manager
    • Outbound-only internet access with fixed addresses → Azure NAT Gateway
    • A fully managed platform with its own front end → Azure App Service
    • The same job on other clouds → compare Elastic Load Balancing and Cloud Load Balancing

    Pros: why consider it?

    Why teams choose it

    • Fast and low-latency, with no proxy for traffic to pass through
    • Zone-redundant frontends and a service-level agreement on Standard
    • Works for any TCP or UDP application
    • Internal and public load balancers use the same building blocks
    • Secure by default: closed until a security group opens it
    • Gateway and global tiers extend it to appliances and several regions

    Trade-offs to weigh

    • No understanding of HTTP: no URL routing, TLS offload or WAF
    • Outbound SNAT port limits catch teams out without a NAT gateway or outbound rules
    • The five-tuple hash balances connections, not load
    • Health probe design is on you, and a shallow probe hides real faults
    • A backend can’t call its own internal front end
    • Several billed parts: rules, data processed, public IPs and NAT gateways

    Common threats, vulnerabilities & risks

    RiskSeverityWhy it mattersMitigation
    Network security group rules that are too wideHighOpening a port to the whole internet exposes every server in the pool.Allow only the ports the service needs, limit source ranges where you can, and review rules regularly.
    Management ports reachable through the load balancerHighInbound NAT rules for SSH or RDP put those ports on a public address.Use Azure Bastion or a VPN instead, and remove inbound NAT rules for administration.
    Still running on the retired Basic SKUHighThe SKU is retired, has no zone support and no service-level agreement, and was open to the internet by default.Inventory Basic load balancers and public IPs, and migrate to Standard now.
    A shallow health probeMediumA TCP probe says the port is open even if the application is broken, so users get errors from servers that look healthy.Use an HTTP or HTTPS probe on a path that checks what matters.
    SNAT port exhaustionMediumOutbound connections fail under load, and the cause is hard to see without metrics.Use a NAT gateway or outbound rules, pool connections and alert on SNAT usage.
    A single zone or regionMediumA zone or regional outage takes the service down.Use zone-redundant frontends and backends across zones, and the global tier or DNS routing for regional failover.
    No logging or metrics alertsMediumProbe failures and SNAT pressure go unnoticed until customers complain.Alert on DipAvailability, VipAvailability and SNAT metrics, and send diagnostics to Log Analytics.
    Default outbound access assumedLow–MedNew virtual networks are moving to private subnets without default outbound access.Plan explicit outbound with a NAT gateway or outbound rules.
    Orphaned load balancers and public IPsLow–MedUnused ones keep billing and widen the attack surface.Tag with an owner and review monthly.

    Performance optimisation

    • Spread backends across availability zones, and use zone-redundant frontends so a zone failure doesn’t remove the entry point.
    • Use HTTP probes with a cheap path, and tune the interval and threshold so failures are detected quickly without flapping.
    • Turn on TCP reset so that applications learn about dropped idle connections at once.
    • Set the idle timeout to match the application, and send keep-alives for long-lived connections.
    • Use a NAT gateway for outbound traffic, and reuse connections to avoid burning SNAT ports.
    • Keep traffic in the same zone and region where you can, to cut latency and data transfer cost.
    • Use client IP persistence only for applications that need it, since it can skew the balance.
    • Test with realistic connection counts, because the hash balances connections and not load.

    Reduce monthly cost

    FinOps is the habit of managing cloud spend together with engineering. These are the FinOps checks that matter most for Azure Load Balancer.

    • Keep the number of rules to what you need, since rules are billed by the hour.
    • Remember that inbound NAT rules aren’t counted, but they expose ports, so use them sparingly.
    • Delete unused load balancers, public IPs and NAT gateways.
    • Compare a NAT gateway with outbound rules for your traffic, since each has its own charges.
    • Watch data processed, and keep chatty traffic inside a zone where the design allows.
    • Use the global tier only when you need cross-region TCP or UDP, since it adds a layer.
    • Choose an internal load balancer for private traffic, which avoids public IP charges.
    • Use Application Gateway or Front Door for web traffic instead of building HTTP features on top of a layer 4 balancer.
    • Tag resources by team, and review cost by resource monthly.
    • Add a budget alert on the resource group.

    Figures here come from Microsoft's pricing page structure and documentation, read in October 2026. The page's exact rates differ by region and currency, so confirm them on the live page (see Pricing).

    Security optimisation

    • Allow only the ports and source ranges that the service needs in the network security group, and review them regularly.
    • Use internal load balancers for private tiers, and keep backend servers without public IPs.
    • Don’t publish SSH or RDP through inbound NAT rules. Use Azure Bastion or a VPN.
    • Allow the AzureLoadBalancer service tag for probes, so a deny rule doesn’t take servers out of the pool.
    • Use NAT gateways for outbound traffic, with fixed addresses that partners can allow-list.
    • Send diagnostic logs and metrics to Log Analytics, and alert on probe and SNAT problems.
    • Use Azure Policy to deny Basic SKU resources and public IPs where they shouldn’t exist.
    • Restrict who can change load balancers and their rules with Azure RBAC, and add resource locks.
    • Put a WAF-capable service (Application Gateway or Front Door) in front of web traffic.
    • Review Microsoft Defender for Cloud recommendations for network exposure.

    Governance & compliance

    Guardrails

    • A shared Bicep or Terraform module for load balancers that creates Standard SKU, zone-redundant frontends, HTTP probes, TCP reset, diagnostics and tags
    • Azure Policy that denies the Basic SKU, public IPs on selected subnets and load balancers without diagnostic settings
    • A naming standard for frontends, pools, probes and rules, so references stay readable
    • A review step for any inbound NAT rule or open management port

    Continuous checks (Azure Policy, Defender for Cloud and your own scripts)

    • A scheduled script that lists load balancers on the Basic SKU, with TCP-only probes, with SNAT left on and no outbound rule, or without TCP reset (the C# tab does this)
    • Azure Policy compliance for SKU, diagnostics and public exposure
    • Alerts on DipAvailability, VipAvailability and SNAT port use
    • An activity log alert for changes to rules, probes and backend pools
    • A monthly report of load balancers and public IPs by cost and owner

    Azure Policy audits and enforces settings, Microsoft Defender for Cloud flags exposed endpoints, while the activity log and Azure Monitor hold changes and metrics, and the Microsoft Service Trust Portal holds compliance reports. Microsoft runs the load balancer platform. Rule and probe design, security group rules, outbound design and the health of your own servers are yours.

    Reduce carbon footprint

    • Delete idle load balancers, public IPs and NAT gateways.
    • Keep traffic within a zone and region where the design allows, to shorten network paths.
    • Right-size the scale set behind it with autoscale, so servers aren’t idle.
    • Use internal frontends for private traffic.
    • Deploy to a region with a cleaner power grid if data rules and latency allow it.
    • Microsoft’s Emissions Impact Dashboard reports per subscription, with no separate figure for Load Balancer, so this page gives none.

    Pricing

    Purchase options

    Standard load balancer Per rule hour, plus per GB

    Billed per rule per hour and per GB processed. The billable count is the number of load balancing and outbound rules, with a first group of rules at one rate and extra rules at another. There is no hourly charge when no rules exist.

    Inbound NAT rules Free

    Inbound NAT rules are not counted in the rules total, though the ports they publish still need protecting.

    Gateway and global tiers Gateway hours and data

    The Gateway SKU bills for gateway and chain hours plus data processed. Traffic from a global load balancer to a regional one carries no additional data processing charge.

    Related resources IPs, NAT gateway, transfer

    Standard public IP addresses, a NAT gateway (by the hour and by data processed) and data transfer out of Azure are billed on their own.

    What you actually pay for

    • Load balancing and outbound rules, per hour
    • Data processed, in both directions, per GB
    • Standard public IP addresses
    • A NAT gateway, by the hour and per GB processed
    • Data transfer between zones and regions, and out to the internet

    Microsoft lists the rule, data processing and gateway meters on its pricing page, and rates differ by region and currency. See the official Azure Load Balancer pricing page and the Azure pricing calculator.

    Important code references

    Two web servers behind a Standard load balancer: a network and security group, a zone-redundant public IP, an HTTP probe, a rule with TCP reset, a NAT gateway for outbound traffic, network interfaces that join the pool and two virtual machines. The CLI tab builds it and reads the probe and data path metrics; Terraform describes the same resources. The Python tab reads probe health per server and SNAT port pressure from Azure Monitor, and the C# tab audits load balancers for the Basic SKU, TCP-only probes, SNAT left on without outbound rules and missing TCP reset. Replace the names and the region with your own.

    # Placeholders: replace the names and the region with your own.
    RG=rg-lb-demo
    LOC=centralindia
    
    az group create --name $RG --location $LOC
    
    # 1. A network, and a security group that lets web traffic in. A Standard load balancer is closed to inbound traffic until a
    #    security group allows it (the retired Basic SKU was open by default).
    az network vnet create --resource-group $RG --name vnet-web --address-prefixes 10.20.0.0/16 --subnet-name web --subnet-prefixes 10.20.1.0/24
    az network nsg create --resource-group $RG --name nsg-web
    az network nsg rule create --resource-group $RG --nsg-name nsg-web --name allow-http --priority 100 --direction Inbound --access Allow \
      --protocol Tcp --source-address-prefixes Internet --destination-port-ranges 80 8080
    
    # 2. A zone-redundant Standard public IP and the load balancer with one front end and one backend pool.
    az network public-ip create --resource-group $RG --name lb-ip --sku Standard --allocation-method Static --zone 1 2 3
    az network lb create --resource-group $RG --name lb-web --sku Standard --public-ip-address lb-ip \
      --frontend-ip-name front --backend-pool-name pool
    
    # 3. A health probe that calls /health every 15 seconds, and a rule that sends port 80 to port 8080.
    #    A server leaves the rotation after two failed probes. TCP reset on idle tells both ends when a connection was dropped,
    #    and outbound SNAT is switched off on the rule because outbound traffic goes through a NAT gateway (step 4).
    az network lb probe create --resource-group $RG --lb-name lb-web --name health --protocol Http --port 8080 --path /health \
      --interval 15 --probe-threshold 2
    az network lb rule create --resource-group $RG --lb-name lb-web --name web --protocol Tcp --frontend-port 80 --backend-port 8080 \
      --frontend-ip-name front --backend-pool-name pool --probe-name health --idle-timeout 4 --enable-tcp-reset true --disable-outbound-snat true
    
    # 4. Outbound traffic: a NAT gateway on the subnet gives the servers a fixed outbound address and plenty of ports.
    az network public-ip create --resource-group $RG --name nat-ip --sku Standard --allocation-method Static
    az network nat gateway create --resource-group $RG --name natgw --public-ip-addresses nat-ip --idle-timeout 10
    az network vnet subnet update --resource-group $RG --vnet-name vnet-web --name web --nat-gateway natgw --network-security-group nsg-web
    
    # 5. Two network interfaces that join the backend pool as they are created, and a server on each.
    for N in 1 2; do
      az network nic create --resource-group $RG --name web-$N-nic --vnet-name vnet-web --subnet web \
        --lb-name lb-web --lb-address-pools pool
      az vm create --resource-group $RG --name web-$N --image Ubuntu2204 --size Standard_B2s --admin-username azureuser \
        --generate-ssh-keys --nics web-$N-nic --no-wait
    done
    
    # 6. Is each server answering its probe, and is the data path up? Both are metrics on the load balancer, split by backend address.
    LB_ID=$(az network lb show --resource-group $RG --name lb-web --query id --output tsv)
    az monitor metrics list --resource $LB_ID --metric DipAvailability --dimension BackendIPAddress --aggregation Average --interval PT5M --offset 1h
    az monitor metrics list --resource $LB_ID --metric VipAvailability --aggregation Average --interval PT5M --offset 1h
    # Placeholders: pass in your own location. The names below are examples.
    variable "location" {
      type    = string
      default = "centralindia"
    }
    
    provider "azurerm" {
      features {}
    }
    
    resource "azurerm_resource_group" "lb" {
      name     = "rg-lb-demo"
      location = var.location
    }
    
    resource "azurerm_virtual_network" "web" {
      name                = "vnet-web"
      address_space       = ["10.20.0.0/16"]
      location            = azurerm_resource_group.lb.location
      resource_group_name = azurerm_resource_group.lb.name
    }
    
    resource "azurerm_subnet" "web" {
      name                 = "web"
      resource_group_name  = azurerm_resource_group.lb.name
      virtual_network_name = azurerm_virtual_network.web.name
      address_prefixes     = ["10.20.1.0/24"]
    }
    
    # A Standard load balancer is closed to inbound traffic until a security group allows it.
    resource "azurerm_network_security_group" "web" {
      name                = "nsg-web"
      location            = azurerm_resource_group.lb.location
      resource_group_name = azurerm_resource_group.lb.name
    
      security_rule {
        name                       = "allow-http"
        priority                   = 100
        direction                  = "Inbound"
        access                     = "Allow"
        protocol                   = "Tcp"
        source_port_range          = "*"
        destination_port_ranges    = ["80", "8080"]
        source_address_prefix      = "Internet"
        destination_address_prefix = "*"
      }
    }
    
    resource "azurerm_subnet_network_security_group_association" "web" {
      subnet_id                 = azurerm_subnet.web.id
      network_security_group_id = azurerm_network_security_group.web.id
    }
    
    resource "azurerm_public_ip" "lb" {
      name                = "lb-ip"
      location            = azurerm_resource_group.lb.location
      resource_group_name = azurerm_resource_group.lb.name
      sku                 = "Standard"
      allocation_method   = "Static"
      zones               = ["1", "2", "3"]
    }
    
    resource "azurerm_lb" "web" {
      name                = "lb-web"
      location            = azurerm_resource_group.lb.location
      resource_group_name = azurerm_resource_group.lb.name
      sku                 = "Standard"
    
      frontend_ip_configuration {
        name                 = "front"
        public_ip_address_id = azurerm_public_ip.lb.id
      }
    }
    
    resource "azurerm_lb_backend_address_pool" "pool" {
      loadbalancer_id = azurerm_lb.web.id
      name            = "pool"
    }
    
    resource "azurerm_lb_probe" "health" {
      loadbalancer_id     = azurerm_lb.web.id
      name                = "health"
      protocol            = "Http"
      port                = 8080
      request_path        = "/health"
      interval_in_seconds = 15
      probe_threshold     = 2
    }
    
    resource "azurerm_lb_rule" "web" {
      loadbalancer_id                = azurerm_lb.web.id
      name                           = "web"
      protocol                       = "Tcp"
      frontend_port                  = 80
      backend_port                   = 8080
      frontend_ip_configuration_name = "front"
      backend_address_pool_ids       = [azurerm_lb_backend_address_pool.pool.id]
      probe_id                       = azurerm_lb_probe.health.id
      idle_timeout_in_minutes        = 4
      enable_tcp_reset               = true
      disable_outbound_snat          = true # outbound traffic goes through the NAT gateway below
    }
    
    # Outbound traffic: a NAT gateway gives the servers a fixed outbound address and plenty of ports.
    resource "azurerm_public_ip" "nat" {
      name                = "nat-ip"
      location            = azurerm_resource_group.lb.location
      resource_group_name = azurerm_resource_group.lb.name
      sku                 = "Standard"
      allocation_method   = "Static"
    }
    
    resource "azurerm_nat_gateway" "web" {
      name                    = "natgw"
      location                = azurerm_resource_group.lb.location
      resource_group_name     = azurerm_resource_group.lb.name
      sku_name                = "Standard"
      idle_timeout_in_minutes = 10
    }
    
    resource "azurerm_nat_gateway_public_ip_association" "web" {
      nat_gateway_id       = azurerm_nat_gateway.web.id
      public_ip_address_id = azurerm_public_ip.nat.id
    }
    
    resource "azurerm_subnet_nat_gateway_association" "web" {
      subnet_id      = azurerm_subnet.web.id
      nat_gateway_id = azurerm_nat_gateway.web.id
    }
    
    # Two network interfaces that join the backend pool. Attach a virtual machine to each, or point a scale set at the pool.
    resource "azurerm_network_interface" "web" {
      count               = 2
      name                = "web-${count.index + 1}-nic"
      location            = azurerm_resource_group.lb.location
      resource_group_name = azurerm_resource_group.lb.name
    
      ip_configuration {
        name                          = "primary"
        subnet_id                     = azurerm_subnet.web.id
        private_ip_address_allocation = "Dynamic"
      }
    }
    
    resource "azurerm_network_interface_backend_address_pool_association" "web" {
      count                   = 2
      network_interface_id    = azurerm_network_interface.web[count.index].id
      ip_configuration_name   = "primary"
      backend_address_pool_id = azurerm_lb_backend_address_pool.pool.id
    }
    
    output "public_ip_address" {
      value = azurerm_public_ip.lb.ip_address
    }
    # pip install azure-monitor-querymetrics azure-identity
    # Reads the load balancer's health probe results per server, and checks whether outbound SNAT ports are running out.
    import datetime as dt
    
    from azure.identity import DefaultAzureCredential
    from azure.monitor.querymetrics import MetricAggregationType, MetricsClient
    
    # Metrics are read from a regional endpoint, so use the region of the load balancer.
    metrics = MetricsClient("https://centralindia.metrics.monitor.azure.com", DefaultAzureCredential())
    NAMESPACE = "Microsoft.Network/loadBalancers"
    
    
    def backend_health(lb_resource_id, hours=1):
        """Average health probe status per backend address over the last hours: 100 means every probe was answered and 0 means none were.
        The load balancer stops sending new connections to a server whose probes fail, so anything below 100 deserves a look."""
        result = metrics.query_resources(
            resource_ids=[lb_resource_id], metric_namespace=NAMESPACE, metric_names=["DipAvailability"],
            timespan=dt.timedelta(hours=hours), granularity=dt.timedelta(minutes=5),
            aggregations=[MetricAggregationType.AVERAGE], filter="BackendIPAddress eq '*'")[0]
        health = {}
        for metric in result.metrics:
            for series in metric.timeseries:
                values = [point.average for point in series.data if point.average is not None]
                if values:
                    backend = next(iter(series.metadata_values.values()), "unknown")
                    health[backend] = sum(values) / len(values)
        return health
    
    
    def snat_pressure(lb_resource_id, hours=1):
        """Highest share of the allocated SNAT ports that was in use. Above about 0.8, outbound connections start to fail, so add
        a NAT gateway or more outbound addresses."""
        result = metrics.query_resources(
            resource_ids=[lb_resource_id], metric_namespace=NAMESPACE, metric_names=["UsedSnatPorts", "AllocatedSnatPorts"],
            timespan=dt.timedelta(hours=hours), granularity=dt.timedelta(minutes=5),
            aggregations=[MetricAggregationType.MAXIMUM])[0]
        peak = {}
        for metric in result.metrics:
            values = [point.maximum for series in metric.timeseries for point in series.data if point.maximum is not None]
            peak[metric.name] = max(values) if values else 0
        return peak["UsedSnatPorts"] / peak["AllocatedSnatPorts"] if peak.get("AllocatedSnatPorts") else 0.0
    
    
    if __name__ == "__main__":
        lb_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-lb-demo/providers/Microsoft.Network/loadBalancers/lb-web"
        for backend, percent in sorted(backend_health(lb_id).items()):
            print("%s: %.0f%% of probes answered" % (backend, percent))
        print("SNAT ports in use: %.0f%%" % (snat_pressure(lb_id) * 100))
    // dotnet add package Azure.ResourceManager.Network
    // dotnet add package Azure.Identity
    // Audits every load balancer in the subscription: the retired Basic SKU, rules that rely on default outbound SNAT,
    // TCP-only probes, and rules without TCP reset.
    using Azure.Identity;
    using Azure.ResourceManager;
    using Azure.ResourceManager.Network;
    using Azure.ResourceManager.Network.Models;
    using Azure.ResourceManager.Resources;
    
    var arm = new ArmClient(new DefaultAzureCredential());
    SubscriptionResource subscription = await arm.GetDefaultSubscriptionAsync();
    int problems = 0;
    
    await foreach (LoadBalancerResource lb in subscription.GetLoadBalancersAsync())
    {
        LoadBalancerData data = lb.Data;
        string name = data.Name;
    
        if (data.Sku?.Name == LoadBalancerSkuName.Basic)
        {
            Console.WriteLine($"{name}: Basic SKU, which Microsoft retired on 30 September 2025, so upgrade to Standard");
            problems++;
        }
    
        foreach (ProbeData probe in data.Probes)
        {
            if (probe.Protocol == ProbeProtocol.Tcp)
            {
                Console.WriteLine($"{name}/{probe.Name}: TCP probe only proves the port is open, so use an HTTP probe for web servers");
                problems++;
            }
        }
    
        bool hasOutboundRules = data.OutboundRules.Count > 0;
        foreach (LoadBalancingRuleData rule in data.LoadBalancingRules)
        {
            if (rule.DisableOutboundSnat != true && !hasOutboundRules)
            {
                Console.WriteLine($"{name}/{rule.Name}: outbound SNAT is left on with no outbound rule, which can run out of ports (use a NAT gateway)");
                problems++;
            }
            if (rule.EnableTcpReset != true)
            {
                Console.WriteLine($"{name}/{rule.Name}: TCP reset is off, so clients learn about idle timeouts late");
                problems++;
            }
        }
    }
    
    Console.WriteLine(problems == 0 ? "No problems found." : $"{problems} problem(s) found.");
    return problems == 0 ? 0 : 1;

    Best videos to explore

    Videos picked for this service. Each one is labelled with its source, opens on YouTube if you prefer, and loads only when you press play.

    Build scalable applications with Azure cross-region Load BalancerOfficial · Microsoft · Intermediate · Watch on YouTube
    Azure Load Balancer insights using Azure Monitor for NetworksOfficial · Microsoft · Intermediate · Watch on YouTube
    What is Azure Load Balancer & How it WorksCommunity video · Beginner · Watch on YouTube
    Azure Load Balancer Deep DiveCommunity video · Intermediate · Watch on YouTube

    Interview questions

    BasicWhat is Azure Load Balancer?

    It’s Azure’s layer 4 load balancer. It receives TCP and UDP traffic on a front end address and spreads connections across healthy servers in a backend pool. It can face the internet with a public address or work inside a network with a private one, and it doesn’t look at HTTP content.

    BasicWhat is the difference between Azure Load Balancer and Application Gateway?

    Azure Load Balancer works at layer 4, so it balances connections quickly without understanding the content. Application Gateway works at layer 7 and understands HTTP: it routes by host and path, terminates TLS, rewrites headers and can run a web application firewall. Many designs use both, with Application Gateway for web traffic and Load Balancer for other tiers.

    BasicWhat do health probes do?

    Each probe tests a backend server regularly, using TCP, HTTP or HTTPS. A server that fails its probes stops receiving new connections until it passes again. The probes come from the address 168.63.129.16, so network rules must allow them.

    IntermediateWhy does a new Standard load balancer seem not to work?

    A Standard load balancer is closed to inbound traffic until a network security group allows it, unlike the retired Basic SKU. Check that a rule allows the frontend port to the servers, that the servers are in the backend pool, that the probe passes, and that the operating system firewall isn’t blocking the port.

    IntermediateWhat is SNAT port exhaustion, and how do you avoid it?

    Servers behind the load balancer reach the internet through source NAT, and each outbound connection to the same destination needs its own port. When many connections use all the ports, new ones fail. A NAT gateway or outbound rules with more addresses supply more ports, connection pooling reduces the need, and the SNAT metrics show how close you are to the limit.

    IntermediateHow does the load balancer choose a backend, and when do you change that?

    By default it hashes the source and destination address, the ports and the protocol, so one connection always goes to one server and different connections spread out. Client IP persistence sends the same client to the same server, which helps stateful applications but can unbalance load. It balances connections, not load, so long-lived connections can skew the result.

    AdvancedHow would you design a zone-redundant internal tier with fast failover?

    Create a Standard internal load balancer with a zone-redundant frontend and place backends in all three zones. Use an HTTP probe on a health path that is cheap and independent of slow dependencies, set the threshold and interval for failover in seconds, and turn on TCP reset. Test by stopping servers and a zone’s worth of servers, and check that clients reconnect cleanly.

    AdvancedHow do you design outbound connectivity for servers behind a load balancer?

    Don’t depend on default outbound access, since new virtual networks are moving to private subnets without it. Attach a NAT gateway to the subnet for the most ports and fixed addresses, or define outbound rules on the load balancer with enough frontend addresses, and disable outbound SNAT on the load balancing rules that you don’t want to use it. Alert on SNAT usage and keep connections pooled.

    AdvancedWhen would you use the Gateway SKU and the global tier?

    Use the Gateway SKU to insert third-party virtual appliances, such as firewalls, into a traffic path without changing the application, because it preserves the original addresses and chains with Standard frontends. Use the global tier when TCP or UDP services run in several regions and you want one anycast address with failover between regional load balancers.

    AdvancedHow would you migrate from the retired Basic SKU to Standard?

    Inventory Basic load balancers and Basic public IPs, then use Microsoft’s migration tooling or recreate them as Standard. Standard needs Standard public IPs and a network security group that allows traffic, so plan those rules first, and decide the outbound method before the cut-over. Test in a copy of the environment, schedule a window, and keep the old load balancer until traffic has moved.

    Similar or alternative services on other clouds

    CapabilityAWSAzureGoogle Cloud
    ServiceElastic Load BalancingAzure Load Balancer and Azure Application GatewayCloud Load Balancing
    HTTP(S), layer 7Application Load BalancerAzure Application Gateway (a separate service)Application Load Balancers
    TCP and UDP, layer 4Network Load BalancerAzure Load Balancer (Standard)Network Load Balancers, proxy and passthrough
    Network appliancesGateway Load BalancerGateway Load Balancer SKUInternal passthrough load balancer as a next hop
    ScopeRegional load balancers, global with Route 53 or Global AcceleratorRegional, with a cross-region tierGlobal with one anycast address, or regional
    Health checksPer target groupHealth probesHealth checks on backend services
    CertificatesACM on the listenerApplication Gateway certificates, Key VaultGoogle-managed or your own
    Web firewallAWS WAF on the Application Load BalancerWAF on Application GatewayCloud Armor
    How you are billedHours plus capacity units, plus IPv4 addressesRules and data processedForwarding rule hours plus data processed

    Typical backends are Azure Virtual Machines and scale sets, and Azure Kubernetes Service creates load balancers for services of type LoadBalancer. For global web traffic in front of it, see Azure Front Door. Metrics and alerts live in Azure Monitor.

    Did you find this article helpful?

    Your answer helps us improve this page for the next reader.

    Sources and further reading

    CloudBrum wrote this page in its own words, using the provider’s public documentation listed below as the reference. Features, limits, names and prices change, so confirm anything that matters on the provider’s own pages before you decide.