Cloud & infrastructure

Upgrade Azure Basic Public IPs to Standard SKU and Keep the Same Address

Basic SKU public IPs were retired on 30 September 2025. Upgrade them to Standard and keep the address, with Microsoft's VM and load balancer scripts or a manual detach and upgrade.

11 min read
On this page

You can upgrade a Basic SKU public IP to Standard and keep the same address because the upgrade changes the SKU of the existing resource rather than allocating a new one. The address must be static and the IP must be disassociated during the upgrade, so for a VM you set the IP to static, detach it, change the SKU to Standard and reattach it, which Microsoft's AzureVMPublicIPUpgrade PowerShell module does for you in a minute or two per VM. Basic load balancers and VPN gateways have their own migration tools that also keep their front-end addresses.

Who this is for and what you will have at the end

This guide is for Azure administrators who still have Basic SKU public IPs on VMs, availability sets, load balancers or gateways after the 30 September 2025 retirement, and need to move them without telling partners, DNS providers or firewall owners about a new address.

At the end you will have:

  • An inventory of Basic public IPs and the resources that use them.
  • Network security groups in place so nothing that worked before is blocked afterwards.
  • Every Basic public IP upgraded to Standard with the same address, using the right tool for each resource type.
  • A verification step that confirms the SKU and the address.

Why the upgrade matters, and what changes

Basic public IPs keep working after retirement, but Microsoft treats them as unsupported and outside SLA. They also block other work: a NAT gateway can't be used in a subnet that contains Basic resources, which matters now that new subnets are private by default (see migrating VMs off default outbound access).

AspectBasic SKUStandard SKU
AllocationDynamic or static (IPv4); dynamic (IPv6)Static only
Inbound securityOpen by defaultSecure by default; an NSG must allow traffic
Availability zonesNot supportedNon-zonal, zonal or zone-redundant
Routing preferenceNot supportedSupported
Standard load balancer, NAT gateway, Azure FirewallNot supportedSupported

Two behaviours catch people out:

  • NSGs become mandatory. Traffic that reached a VM through a Basic IP with no NSG is blocked after the upgrade until an NSG allows it.
  • Zones. An upgraded IP doesn't show zones in its properties. Microsoft's documentation describes upgraded IPs as zone-redundant in most cases in one place and as having no zones in another, so if you need an IP you can attach to a zonal or zone-redundant resource, the guidance is to create a new Standard IP rather than upgrade. A Basic IP that already had a specific zone keeps it.

Prerequisites

  • Network Contributor or a custom role with Microsoft.Network/publicIPAddresses/read, /write and /join/action, plus rights on the NICs and VMs involved.
  • The latest Az PowerShell module. Microsoft recommends PowerShell 7 or later for the load balancer upgrade module, although Windows PowerShell 5.1 is supported.
  • Permission in your organization to install and run modules from the PowerShell Gallery.
  • No resource locks on load balancers, their resource groups or related resources if you're upgrading a load balancer.
  • A maintenance window. A VM is unreachable at its public IP for the minutes it takes to detach, upgrade and reattach.

Step 1: Inventory Basic public IPs

List every Basic public IP you can read, with its allocation method:

resources
| where type =~ 'microsoft.network/publicipaddresses'
| where sku.name =~ 'Basic'
| project
    ResourceId = tolower(id),
    ResourceName = name,
    AllocationMethod = tostring(properties.publicIPAllocationMethod),
    Region = location,
    ResourceGroupName = resourceGroup,
    SubscriptionId = subscriptionId

Then list the VMs that have Basic IPs attached. This is Microsoft's query; run it in Resource Graph Explorer or wrap it in Search-AzGraph -Query:

Resources
| where type =~ 'microsoft.compute/virtualmachines'
| project vmId = tolower(id), vmNics = properties.networkProfile.networkInterfaces
| join (
  Resources |
  where type =~ 'microsoft.network/networkinterfaces' |
  project nicVMId = tolower(tostring(properties.virtualMachine.id)), allVMNicID = tolower(id), nicIPConfigs = properties.ipConfigurations)
  on $left.vmId == $right.nicVMId
| join (
  Resources
  | where type =~ 'microsoft.network/publicipaddresses' and isnotnull(properties.ipConfiguration.id)
  | where sku.name == 'Basic'
  | project pipId = id, pipSku = sku.name, pipAssociatedNicId = tolower(tostring(split(properties.ipConfiguration.id, '/ipConfigurations/')[0])))
  on $left.allVMNicID == $right.pipAssociatedNicId
| project vmId, pipId, pipSku

And the Basic load balancers:

Resources
| where type == 'microsoft.network/loadbalancers' and sku.name == 'Basic'

Step 2: Pick the upgrade path for each resource

Resource using the Basic IPPathAddress kept?
Standalone VMAzureVMPublicIPUpgrade moduleYes
VMs in an availability setAzureAvSetBasicPublicIPUpgrade moduleYes
VM whose NIC is in a Basic load balancer poolAzureBasicLoadBalancerUpgrade module (upgrades the LB and the IPs together)Yes for VMs and LB front ends
Disassociated Basic IPPortal, az network public-ip update or Set-AzPublicIpAddressYes
Uniform scale set with per-instance public IPsNot a public IP resource; replace with Standard IP configurationsNo, new addresses
VPN gateway (VpnGw1-5 or legacy SKU)VPN Gateway Basic IP migration toolYes
Basic SKU VPN gatewayRemove the Basic public IP referenceYes
ExpressRoute gatewayExpressRoute gateway migration experienceNot covered here; see Microsoft's ExpressRoute gateway migration guidance
Application Gateway v1Migrate to v2 (v1 retired 28 April 2026)Not by this process

VPN gateways are covered separately in the VPN Gateway SKU migration guide, because the IP upgrade also changes the gateway SKU.

Step 3: Put NSGs in place first

The VM and availability set scripts refuse to upgrade a VM unless an NSG is associated with either the NIC or the subnet of every IP configuration that has a public IP. That requirement exists because Standard IPs drop unsolicited inbound traffic.

For each VM in scope:

  1. Record the inbound ports that clients use today, such as 443 for a web server or a management port reached only from a jump host.
  2. Associate an NSG with the NIC or subnet and add allow rules for exactly that traffic, scoped to known source ranges where you can.
  3. Test that the rules don't break anything while the IP is still Basic.

Step 4: Upgrade VM public IPs with the module

Install the module and connect to the right tenant and subscription:

Install-Module -Name AzureVMPublicIPUpgrade -Scope CurrentUser -Repository PSGallery -Force
Connect-AzAccount -Tenant <TenantId> -Subscription <SubscriptionId>

Check that a VM is supported without changing anything:

Start-VMPublicIPUpgrade -VMName 'vm-web-01' -ResourceGroupName 'rg-web' -WhatIf

Then upgrade it:

Start-VMPublicIPUpgrade -VMName 'vm-web-01' -ResourceGroupName 'rg-web'

To upgrade every VM in a resource group and skip any VM without an NSG:

Get-AzVM -ResourceGroupName 'rg-web' | Start-VMPublicIPUpgrade -skipVMMissingNSG

The module sets each IP to static, confirms it's static, disassociates it, changes the SKU to Standard and reassociates it. Microsoft's testing shows 1 to 2 minutes for a VM with one NIC and one public IP, about another minute per extra NIC, and a few seconds per extra public IP. Activity is logged to PublicIPUpgrade.log in the working directory.

VMs in an availability set

Use the availability set module, which processes all VMs in the set:

Install-Module -Name AzureAvSetBasicPublicIPUpgrade -Scope CurrentUser -Repository PSGallery -Force
Start-AzAvSetPublicIPUpgrade -availabilitySetName 'avset-web' -resourceGroupName 'rg-web' -WhatIf
Start-AzAvSetPublicIPUpgrade -availabilitySetName 'avset-web' -resourceGroupName 'rg-web'

Its log file is AvSetPublicIPUpgrade.log.

Step 5: Upgrade an IP manually

For a Basic IP that isn't attached to anything, or when you prefer to control each step, the upgrade needs a static, disassociated IP.

Set the allocation method to static. This step doesn't change the address of an IP that's already in use:

az network public-ip update --resource-group rg-web --name pip-web-01 --allocation-method Static

Dissociate it from the NIC's IP configuration:

az network nic ip-config update \
 --name ipconfig1 \
 --resource-group rg-web \
 --nic-name nic-web-01 \
 --public-ip-address null

Upgrade the SKU, then confirm it:

az network public-ip update --resource-group rg-web --name pip-web-01 --sku Standard
az network public-ip show --resource-group rg-web --name pip-web-01 --query sku --output tsv

Reattach it to the same IP configuration:

az network nic ip-config update \
 --name ipconfig1 \
 --resource-group rg-web \
 --nic-name nic-web-01 \
 --public-ip-address pip-web-01

The PowerShell equivalent of the static and SKU changes uses Set-AzPublicIpAddress:

$pubIP = Get-AzPublicIpAddress -Name 'pip-web-01' -ResourceGroupName 'rg-web'
$pubIP.PublicIpAllocationMethod = 'Static'
Set-AzPublicIpAddress -PublicIpAddress $pubIP
 
# after the IP has been dissociated from the NIC
$pubIP = Get-AzPublicIpAddress -Name 'pip-web-01' -ResourceGroupName 'rg-web'
$pubIP.Sku.Name = 'Standard'
Set-AzPublicIpAddress -PublicIpAddress $pubIP

In the portal, open the disassociated IP, select the upgrade banner on Overview, select I acknowledge and then Upgrade.

Step 6: Upgrade Basic load balancers and their IPs

A VM's public IP and its load balancer must use the same SKU, so VMs behind a Basic load balancer are upgraded with the load balancer module. It removes the Basic load balancer before it creates the Standard one, so plan downtime.

Install-Module -Name AzureBasicLoadBalancerUpgrade -Scope CurrentUser -Repository PSGallery -Force
Select-AzSubscription -Subscription <SubscriptionId>
 
Start-AzBasicLoadBalancerUpgrade -ResourceGroupName 'rg-web' -BasicLoadBalancerName 'lb-web' -validateScenarioOnly:$true
Start-AzBasicLoadBalancerUpgrade -ResourceGroupName 'rg-web' -BasicLoadBalancerName 'lb-web' -RecoveryBackupPath C:\BasicLBRecovery

What the module keeps and changes:

  • Public front-end IPs are converted to static and upgraded to Standard, so the address is kept. Internal front ends try to reuse the same private IP.
  • Health probes, load-balancing rules, inbound NAT rules and backend pools are migrated. NAT pools become NAT rules unless you pass -skipUpgradeNATPoolsToNATRules.
  • Instance-level public IPs on VMs keep their addresses. Uniform scale set instance IPs change, because they can only be replaced.
  • For public load balancers it creates an outbound rule (when there is one backend pool) and an NSG if none exists.
  • Internal load balancers get no outbound path. Plan a NAT gateway, an NVA or a secondary outbound-only load balancer before you migrate.

Migrate load balancers that share backend members, such as an internal and external pair, together with -MultiLBConfig.

Verify the upgrade

  • Confirm the SKU: az network public-ip show ... --query sku --output tsv returns Standard, or the portal Overview shows Standard.
  • Confirm the address is unchanged: compare az network public-ip show ... --query ipAddress with your inventory.
  • Test inbound application traffic from outside Azure and outbound traffic from the VM.
  • Re-run the Basic public IP query; the result set should shrink to the items you deliberately left for other tools.
  • For load balancers, run the module with -validateCompletedMigration and the state file it created.

Troubleshooting

Warning that the IP can't be upgraded. The IP is dynamic. Change it to static first; Standard IPs don't support dynamic allocation.

The upgrade is blocked because the IP is associated. Only disassociated IPs can be upgraded manually. Detach it or use the VM module, which does the detach for you.

The script skips a VM. The VM has no NSG on its NIC or subnet, or its NIC is in a load balancer backend or NAT pool. Add an NSG, or use the load balancer module.

Inbound traffic stopped after the upgrade. The NSG doesn't allow the traffic. Add the allow rule; Standard IPs are closed by default.

The VM dropped out of an Application Gateway backend pool. The VM module removes the NIC from the pool. Add it back, or define the backend by private IP address before you run the script.

The VM upgrade failed part-way. Rerun with the recovery file: Start-VMPublicIPUpgrade -RecoverFromFile ./PublicIPUpgrade_Recovery_<timestamp>.csv -VMName 'vm-web-01' -ResourceGroupName 'rg-web'. The address isn't lost because it was made static first.

The load balancer migration failed. Fix the cause in Start-AzBasicLoadBalancerUpgrade.log, then rerun with -FailedMigrationRetryFilePathLB (and -FailedMigrationRetryFilePathVMSS for scale sets). The approach is fail forward; the upgraded IP can't go back to a Basic load balancer.

An internal load balancer upgrade fails on the private IP. The module tries to reassign the private front-end IP released when the Basic load balancer is deleted, and fails if that address isn't available. Resolve the conflict, then retry with the backup state file.

Checklist

  • Basic public IPs, attached VMs and Basic load balancers inventoried.
  • NSGs associated and tested on every VM that receives inbound traffic.
  • Dynamic IPs switched to static before any detach.
  • Standalone VMs upgraded with AzureVMPublicIPUpgrade, availability sets with AzureAvSetBasicPublicIPUpgrade.
  • Basic load balancers upgraded with AzureBasicLoadBalancerUpgrade, with outbound connectivity planned for internal ones.
  • VPN gateways moved with the VPN Gateway migration tool.
  • SKU and address verified for every IP; Basic query returns nothing unexpected.

References

Questions people ask

Does upgrading a Basic public IP to Standard change the IP address?

No, as long as the address is static before you detach it. Upgrading a public IP resource retains the address, and Microsoft's upgrade scripts set the allocation method to static before they disassociate the IP so the address is kept even if the script fails.

Will my VM stop accepting traffic after the upgrade?

It will if there's no network security group allowing the traffic. Standard public IPs are secure by default and closed to inbound traffic, while Basic IPs were open. Associate an NSG with the NIC or subnet that allows the required ports before you upgrade.

Can I roll back a Standard public IP to Basic?

No. Upgrading a Basic public IP to Standard can't be reversed, and you can't downgrade a public IP from Standard to Basic. Use the -WhatIf parameter on Microsoft's VM upgrade script to check a VM before you make the change.

What happens to Basic public IPs that are not upgraded?

Microsoft states that Basic public IPs remain operational after the 30 September 2025 retirement, but customers who keep using them accept that the service is unsupported and not covered by SLA guarantees.

Azure Public IPAzure Virtual NetworkAzure Load BalancerAzure PowerShellAzure Resource Graph
  1. Azure Default Outbound Access Retirement: Migrate VMs to NAT Gateway

    New Azure virtual networks now get private subnets with no default outbound access. Find the VMs that depend on it, add a NAT gateway, make the subnet private and verify egress.

  2. Azure VM Disaster Recovery with Site Recovery: Setup and Test Failover

    Replicate Azure VMs to a secondary region with Azure Site Recovery, prepare networking and recovery plans, and run a test failover that leaves production untouched.

  3. Azure VPN Gateway SKU Migration: Move Legacy and Non-AZ SKUs to VpnGw AZ

    Standard, High Performance and non-zonal VpnGw1-5 gateways are past their deadlines. Find each gateway's path to a VpnGw AZ SKU, migrate the Basic IP, upgrade the SKU and verify tunnels.