Skip to content
case CS-001 cost optimization

89 Idle Azure VMs Costing $18,400 a Month: An Acquisition Cleanup Case Study

An anonymized case study: 89 Azure VMs left over from an acquisition ran at near-zero CPU for six months, costing a technology startup $18,400 a month. How they were found, verified and removed.

Updated Cloud Sleuth

Engagement details

Resources reviewed
247
Costs analyzed
$51,200/month
Time spent
8 hours
Azure MonitorAzure Cost Management + BillingVM utilization analysisTag audit

Outcome

Monthly savings
$18,400
Annual savings
$220,800
Resources cleaned
89
Risk level
LOW
Client satisfaction
10/10

Summary

  • Client: A technology startup running on Azure (anonymized).
  • Problem: The monthly Azure bill reached $51,200, nearly double its normal level.
  • Finding: 89 virtual machines from an acquired company’s development and staging environments had run at near-zero CPU for more than six months, costing $18,400 a month.
  • Outcome: All 89 VMs were removed over 30 days, with snapshots taken first and no operational impact. Savings: $18,400 a month, or $220,800 a year.
  • Root cause: Nobody owned the resources after the acquisition, so nobody was responsible for removing them.

The situation

When the client’s Azure bill reached $51,200 in a single month, nearly double its usual level, the CFO asked us to find out why. Within the first few hours, the cause was clear: 89 virtual machines that were fully provisioned, with premium storage and static public IP addresses, but doing no useful work.

The VMs had averaged close to 0% CPU for more than six months. Nobody on the current engineering team had created them, and nobody could say what they were for.

What we found

The VMs themselves were easy to identify. The more useful question was how they had come to exist, and why nothing had caught them. Three factors explained it:

  1. They were left over from an acquisition. The VMs belonged to the development and staging environments of a company the client had acquired eight months earlier. They were supposed to be decommissioned during the technical migration, and weren’t.
  2. They had no environment tags. Without tags marking them as development or staging, the VMs were excluded from the regular dev/test auto-shutdown schedules.
  3. Nobody owned them. The team that created the VMs had left during the acquisition, and no one on the client’s side had taken over responsibility for them.

The evidence

Azure Monitor’s historical performance data showed a clear difference between these VMs and the rest of the estate:

VM CPU utilization (6-month average)
------------------------------------
Production fleet:     47.3%
Marketing cluster:    38.1%
Idle acquired VMs:     0.2% (mostly from automated patching)

The cost breakdown for the 89 VMs:

  • VM compute: $12,400/month
  • Premium storage: $4,200/month
  • Static public IPs and networking: $1,800/month
  • Total: $18,400/month

Resolution

After documenting the findings and confirming the VMs were unused, we carried out the cleanup in three phases.

Phase 1: Immediate cost control

  • Took snapshots of every disk, in case any of the data was needed later
  • Stopped and deallocated all 89 VMs, which removed the $12,400 a month in compute charges immediately

Phase 2: Verification and removal

  • Confirmed with every department head that none of the VMs or their data were needed
  • Released the static public IP addresses and moved the remaining disks off Premium SSD
  • Followed a 30-day decommissioning plan before final deletion

Phase 3: Prevention

  • Introduced mandatory tagging policies for new resources
  • Set up a weekly report of orphaned and unowned resources
  • Required an owner to be assigned for every new resource
  • Added cloud resources to the company’s acquisition integration checklist

Outcome

The client saved $18,400 a month, or $220,800 a year, with no impact on operations. The prevention measures are now part of the client’s standard cloud governance process.

Traditional monitoring hadn’t caught the problem because nothing was failing. The VMs were healthy and responsive. They just weren’t doing anything useful, and no alert is designed to detect that.

Lessons for your organization

If this situation sounds familiar, three steps are worth taking now:

  1. Run a VM utilization report across your whole cloud estate, looking for VMs with consistently low CPU and memory use over several months.
  2. Require an owner and a purpose for every resource, with tags or, better, with ownership rules that apply even when tags are missing.
  3. Audit for orphaned and unowned resources at least monthly, and after every acquisition, reorganization or migration.

Find idle resources in your own subscriptions

These 89 VMs ran idle for more than six months because their original team had left during the acquisition, and nobody on the current team could say who owned them or what they were for. Cloud Sleuth is being built as the ownership and context layer for cloud infrastructure, so every resource has a clear answer to who owns it, what it’s actually for and whether it should still exist. The Cloud Sleuth CLI will run on your machine or in your VPC, so nothing leaves your environment, and will cover Azure and AWS from launch, showing unowned resources, common orphans and basic allocation gaps in your own subscriptions and accounts. Both the local tool and Cloud Sleuth Cloud are pre-launch. Get early access.

Cloud Sleuth CLI

Find out who owns your AWS and Azure resources

Get early access to the free Cloud Sleuth CLI. It maps your accounts, puts an owner on every resource, tagged or not, and shows what's safe to remove. It runs on your machine or in your VPC, and nothing leaves your environment.

Related case studies

case CS-003

23.2 TB of Inactive S3 Data: A Storage Ownership Case Study

An anonymized case study: 23.2 TB of S3 data had gone untouched for more than two years, and much of it had no clear owner. How access analysis and owner interviews moved it to Glacier Deep Archive without deleting a file.

$523 /mo saved 10 hours to solve