Back to Blog
FinOps
3 min read

Finding and Cleaning Up Orphaned Azure Resources

AzureCost OptimisationCleanupFinOps

When you delete a VM in Azure, it doesn't automatically delete everything associated with it. Disks, network interfaces, and public IPs often get left behind - still billing you every month.

We call these "orphaned resources," and they're in almost every Azure environment we assess.

What Gets Orphaned?

Managed Disks - The most common culprit. Delete a VM and its OS disk and data disks remain, still incurring storage costs.

Network Interfaces - NICs persist after VM deletion. They're cheap individually but add up.

Public IP Addresses - These aren't free. A static public IP costs around £3/month whether it's attached to anything or not.

Network Security Groups - Often created per-VM and left behind.

Snapshots - Taken for backup purposes and forgotten about.

Unattached Premium SSDs - These are expensive. A P30 (1TB) costs ~£100/month whether it's attached or not.

Finding Orphaned Resources

Azure Portal

Disks:

  1. Go to Disks
  2. Add filter: "Disk state" = "Unattached"
  3. Review and delete

Public IPs:

  1. Go to Public IP addresses
  2. Add column: "Associated to"
  3. Look for blanks

NICs:

  1. Go to Network interfaces
  2. Add column: "Virtual machine"
  3. Look for blanks

Azure Resource Graph

More powerful for larger environments. Run these queries in Resource Graph Explorer:

Unattached Disks:

Resources
| where type == "microsoft.compute/disks"
| where properties.diskState == "Unattached"
| project name, resourceGroup, sku.name, properties.diskSizeGB, subscriptionId

Unassociated Public IPs:

Resources
| where type == "microsoft.network/publicipaddresses"
| where properties.ipConfiguration == ""
| project name, resourceGroup, subscriptionId

Orphaned NICs:

Resources
| where type == "microsoft.network/networkinterfaces"
| where isnull(properties.virtualMachine)
| project name, resourceGroup, subscriptionId

Azure Advisor

Azure Advisor now flags some orphaned resources under Cost recommendations. Check there as a starting point, but it doesn't catch everything.

Real World Example

A recent client had:

  • 47 unattached managed disks
  • 23 orphaned NICs
  • 12 unassociated public IPs
  • 8 old snapshots from 2023

Total monthly waste: £340

Not a massive amount, but it's pure waste. Over a year, that's £4,000 - enough to fund some actual improvements.

Cleanup Process

Before deleting anything:

  1. Document what you find - Export the list to CSV
  2. Check with resource owners - That "orphaned" disk might be deliberately kept for recovery
  3. Check for dependencies - Some disks are detached temporarily for maintenance
  4. Delete in batches - Don't select-all and delete

Safe Deletion Script

For disks, I usually use a two-stage process:

# First, list what we'd delete (dry run)
az disk list --query "[?diskState=='Unattached'].{Name:name, RG:resourceGroup, Size:diskSizeGb}" -o table

# Then delete with confirmation
az disk list --query "[?diskState=='Unattached'].id" -o tsv | while read id; do
  echo "Deleting: $id"
  az disk delete --ids "$id" --yes
done

Prevention

Better than cleaning up is not creating orphans in the first place:

Delete associated resources with VMs: When deleting a VM in the portal, there's a checkbox to delete the NIC, public IP, and disks. Use it.

Use Terraform/Bicep: Infrastructure as Code ensures resources are created and destroyed together.

Regular audits: Run the Resource Graph queries monthly. Add them to your FinOps routine.

Tagging: Tag resources with owners and expiry dates. Makes cleanup decisions easier.


Want us to find your orphaned resources? Our free savings snapshot includes a complete orphaned resource audit.

How mature is your cloud cost management?

Take our free 2-minute FinOps maturity test and get a personalised improvement roadmap.