Stop Buying Reserved Instances on Top of Waste
- Logan Hemphill

- 3 hours ago
- 7 min read
Your team is probably spending $15K to $30K per month on Azure resources nobody is using. And if your first instinct is to buy reserved instances to save money, you're locking in a discount on waste.
I see this pattern constantly. A director gets pressure from the CFO to reduce the cloud bill. Someone on the team pulls up the Azure pricing calculator, does the math on reserved instances, and commits to a one year or three year term. The bill drops 30% on paper. Everyone celebrates.
Six months later, the bill is climbing again. The reservations are still active, but so are the 40 idle VMs, 200 orphaned disks, and a dev environment that runs 24/7 for a team of five people who leave at 5pm.
The math most teams skip
Reserved instances save you up to 72% compared to pay as you go pricing on a specific VM SKU. Savings plans save up to 65% with more flexibility across SKUs and regions. Those are real numbers from Microsoft's own pricing pages.
But here's what those numbers assume: you're actually using the compute you're paying for.
Flexera's 2026 State of the Cloud report found that organizations waste an average of 32% of their cloud spend. For a company spending $50K per month on Azure, that's $16K per month going to resources that aren't doing anything. That's $192K per year.
A three year reserved instance on a Standard_D4s_v5 in East US costs roughly $51.86 per month versus $140.16 per month on pay as you go. That's a savings of $88.30 per month, or $1,060 per year per VM.
Now compare that to simply turning off a VM nobody is using. That's $140.16 per month back. $1,682 per year. Still 60% more savings than the reservation, and you didn't have to commit to anything.
The reservation gets you a discount on the thing you're running. The cleanup gets you 100% back on the thing you shouldn't be running. Cleanup wins every time.
Where the waste actually lives
I've looked at dozens of Azure environments over the past few years, and the waste follows a predictable pattern. It's not hiding in some obscure service. It's sitting in plain sight.
Idle VMs that nobody remembers
Every environment has them. A VM spun up for a proof of concept six months ago. A dev box somebody requested for a project that got cancelled. A staging environment for a feature that shipped in Q2. These VMs are running 24/7, burning compute, and nobody on the team can tell you what they do.
The worst part is that these VMs also have disks, network interfaces, public IPs, and sometimes load balancers attached. One idle VM can easily cost $200 to $400 per month when you add up all the associated resources.
Orphaned disks
When someone deletes a VM through the Azure portal, the default behavior doesn't delete the managed disk. So the disk stays. Premium SSD P30 disks (1 TiB) cost roughly $136 per month. I've seen environments with 50 to 100 orphaned disks. That's $6,800 to $13,600 per month for storage that holds data from VMs that no longer exist.
Dev environments that never sleep
This one is almost universal. Your dev and test environments are running the same hours as production. Your developers work 8 to 10 hours a day. Those VMs are running 24 hours a day. That means 58% to 67% of that compute spend is pure waste.
A team with 10 D4s_v5 VMs in dev is spending about $1,400 per month on compute. If those VMs only need to run during business hours on weekdays, you could shut them down nights and weekends and save roughly $930 per month. That's $11,160 per year from one simple automation.
Public IPs nobody is using
An idle Standard SKU public IP in Azure costs about $3.65 per month. That sounds trivial until you find 40 of them attached to nothing. That's $146 per month, or $1,752 per year, for IP addresses sitting in your subscription doing absolutely nothing.
How to find the waste before buying anything
Before you sign a single reservation or savings plan, run these queries. They take five minutes and they'll show you exactly what you're paying for that you shouldn't be.
Find orphaned managed disks
Open Azure Resource Graph Explorer in the portal and run this:
Resources
| where type has "microsoft.compute/disks"
| extend diskState = tostring(properties.diskState)
| where managedBy == "" or diskState == 'Unattached'
| extend sizeGB = tostring(properties.diskSizeGB)
| extend sku = tostring(properties.sku.name)
| project name, resourceGroup, location, diskState, sizeGB, sku, subscriptionId
| order by sizeGB desc
This returns every managed disk in your environment that isn't attached to a VM. Sort by size and SKU to figure out what's costing you the most. A Premium_LRS P30 sitting unattached is roughly $136 per month. A Premium_LRS P10 runs about $19.71 per month. Even the small ones add up when you have dozens of them.
Find orphaned public IPs
Resources
| where type =~ 'microsoft.network/publicipaddresses'
| extend ipConfig = properties.ipConfiguration.id
| where isempty(ipConfig)
| extend natGateway = properties.natGateway.id
| where isempty(natGateway)
| extend sku = tostring(properties.sku.name)
| project name, resourceGroup, location, sku, subscriptionId
| order by name asc
Every result here is a public IP you're paying for that isn't attached to anything. Standard SKU public IPs cost money even when idle. Basic SKU public IPs were retired in September 2025 and can no longer be created. If you still have legacy Basic SKU IPs, they need to be migrated to Standard SKU.
Find VMs with near zero CPU
This one uses Azure Monitor data. Go to your Log Analytics workspace and run:
InsightsMetrics
| where Namespace == "Processor" and Name == "UtilizationPercentage"
| where TimeGenerated > ago(30d)
| summarize AvgCPU = avg(Val) by Computer
| where AvgCPU < 5
| order by AvgCPU asc
Any VM averaging under 5% CPU over 30 days is a candidate for shutdown or right sizing. I typically find that anything under 2% hasn't had real traffic in weeks. The owners just forgot about it.
The right order of operations
Here's what I tell every client: don't optimize the price of what you're running until you've stopped paying for what you're not running.
The sequence matters:
First, kill the waste. Run the queries above. Delete orphaned disks. Deallocate idle VMs. Shut down dev environments on a schedule. Remove unused public IPs. This is free money. There's no commitment, no contract, no risk. You just stop paying for things you aren't using.
Second, right size what's left. After cleanup, look at what's still running and check if it's the right size. A VM averaging 15% CPU on a D4s_v5 should probably be a D2s_v5 at half the cost. Azure Advisor will give you recommendations here, but take them with a grain of salt. Advisor doesn't know your workload patterns. It just sees the metrics.
Third, now buy your commitments. Once you've cleaned up and right sized, you actually know what your baseline compute looks like. That's when reserved instances and savings plans make sense. You're committing to resources you've verified you need, at the sizes you've verified are correct.
Buying reservations before cleanup is like getting a bulk discount on groceries before checking if half the fridge is already full of food that's going bad.
Automate the cleanup so it sticks
Finding waste once is useful. Keeping it from coming back is the real win. Here are three things I set up for every client:
Auto shutdown for dev/test VMs. Azure has a built in auto shutdown feature at the VM level, but it only handles shutdown, not startup. For proper schedules, use Azure Automation with a runbook or use Start/Stop VMs v2 (the Azure Functions based solution). Set dev VMs to shut down at 7pm and start at 7am on weekdays. That alone cuts dev compute costs by 58%.
Azure Policy for tagging. If you can't tell who owns a resource and why it exists, you can't decide whether to delete it. Deploy a policy that requires an Owner tag and a Project tag on every resource group. If there's no tag, there's no owner. If there's no owner, the resource is a deletion candidate.
Monthly orphan sweeps. Schedule a recurring Azure Resource Graph query that emails results to your FinOps team (or your engineering leads if you don't have a FinOps team). The query takes 30 seconds. Reviewing the results takes 10 minutes. The savings compound every month.
What this looks like in practice
I worked with a mid market company last year that was spending $62K per month on Azure. Their first instinct was to buy reserved instances across the board. Before they did that, we ran the cleanup playbook.
We found $8,200 per month in orphaned disks. Another $4,100 per month in idle VMs that hadn't served traffic in 60+ days. Their dev environment was running 24/7 for a team that worked 9 to 5 Eastern, costing an extra $3,800 per month in after hours compute.
Total waste: $16,100 per month. That's $193,200 per year.
After the cleanup, their actual compute baseline was $45,900 per month. We helped them right size a few oversized VMs, dropping it further to about $41,000. Then they bought savings plans and reservations on top of the clean baseline.
Final bill: roughly $31,000 per month, down from $62,000. A 50% reduction. And the biggest chunk of those savings came from cleanup, not from commitments.
The uncomfortable truth about reservations
Reserved instances are a good tool. Savings plans are a good tool. But they're step three, not step one. Every month you spend committed to idle resources is a month you've locked yourself into waste at a discount.
Don't buy a discount on resources you haven't verified you need. Clean up first. Right size second. Commit third.
If this sounds like your environment, I do free 30 minute Azure cost reviews. It's a conversation to see if there's a fit, not a sales pitch.
_(1).webp)


Comments