Azure bills grow the way gardens grow weeds: not through any single bad decision, but through the steady accumulation of things nobody is looking at. For a small team without a FinOps function, the good news is that cost hygiene has a steep value curve — a handful of low-effort practices capture most of the savings that a dedicated cost programme would find. This guide orders those practices by effort, explains the maths behind the biggest one, and ends with the monthly habit that keeps the garden weeded.
The always-on tax
The core insight behind most cloud waste: Azure charges for allocation, not use. A VM bills the same whether it's at 90% CPU or sitting idle; a premium disk bills whether or not anything reads it; a public IP bills while attached to nothing. On-prem, idle hardware was a sunk cost; in the cloud, idleness is a recurring invoice.
The tax is largest on compute, because compute is priced by the hour and most non-production compute is only needed during working hours. A month has about 730 hours; a working month — say 10 hours a day, 21 weekdays — is about 210. A dev VM running 24/7 is paying for roughly 3.5× the hours anyone uses. Multiply across every dev, test, staging and demo VM in the subscription and you have, in most organisations, the single largest recoverable line on the bill.
With the framing set, here are the wins in ascending order of effort.
Win 1: delete orphaned resources (effort: an afternoon)
The free money tier. When VMs are deleted, their attachments frequently survive:
- Unattached managed disks — the classic. Deleting a VM does not necessarily delete its disks, and premium SSD pricing means a forgotten 512 GB P20 quietly costs real money every month, forever. Filter the disk list by unattached state and review everything there.
- Unassociated public IPs — small individually, numerous collectively, and each one is also a bit of attack surface you don't need.
- Old snapshots and images — created for one migration or backup moment in 2023, never deleted, billing by the GB since.
- Empty or idle infrastructure: load balancers fronting nothing, app service plans hosting zero apps (a plan bills whether or not it has apps), stopped-but-not-deallocated VMs (a VM stopped from inside the OS still bills for compute — only a deallocated VM stops the meter; check for the "stopped" versus "stopped (deallocated)" status).
Azure Advisor's cost recommendations and a Resource Graph query will surface most of this. The first pass through a subscription that's a few years old is almost always startling. Delete with normal caution — confirm a disk really is orphaned rather than detached-on-purpose — and put a quarterly repeat in the calendar, because orphans regenerate.
Win 2: schedule dev/test compute (effort: a day to set up)
The biggest structural saving for most small teams, per the maths above: stopping non-production VMs outside working hours removes 60–70% of their compute cost with zero impact on anyone, because nobody was using them anyway.
The implementation options range from Azure's built-in auto-shutdown (per-VM daily stop time — easy, but stop-only, so mornings mean manual starts) through DIY Automation runbooks or Functions, up to purpose-built scheduling products that handle start and stop, calendars, exceptions and self-service. The dev/test VM scheduling patterns guide compares the patterns and the realistic savings math in detail; the short version is that an office-hours schedule on a dev/test estate reliably cuts its compute bill by well over half.
Two footnotes that keep expectations honest: deallocated VMs still pay for their disks and static IPs, so scheduling cuts the compute line, not the whole resource cost; and anything with state that matters (a database VM colleagues in other time zones query at odd hours) needs a schedule that reflects reality rather than headquarters' office hours.
Win 3: right-size what stays on (effort: a few days, ongoing)
For VMs that genuinely must run continuously, the question becomes whether they're the right size. Azure Advisor flags underutilised VMs based on actual metrics; a VM averaging 4% CPU on an 8-vCPU size is a resize candidate, and moving down one size tier roughly halves that VM's compute cost. The same logic applies to over-provisioned databases (DTUs/vCores), app service plans, and premium disks whose IOPS nobody uses.
Right-sizing is second on the effort scale because it requires judgment — peak load matters more than average, resizing needs a restart window, and some workloads have memory or IOPS floors that metrics don't obviously show. Do it deliberately, one class of workload at a time, and re-check quarterly since workloads drift.
Once the always-on set is stable and right-sized, reservations or savings plans on that set are the final optimisation — one to three years of commitment in exchange for substantial discounts. Do this last: committing to instances you should have deleted, scheduled or shrunk locks in the waste. The correct order is always hygiene first, commitment second.
Win 4: storage tiers and lifecycle (effort: a few days)
Storage is rarely the headline number but compounds forever. The wins:
- Blob access tiers. Data written once and read rarely doesn't belong in the hot tier. Cool and archive tiers cost a fraction per GB (with retrieval costs and, for archive, retrieval latency as the trade-off). Lifecycle management rules automate the transition — move blobs untouched for 90 days to cool, archive or delete after a year — set once per storage account and left to run.
- Log and backup retention. Log Analytics workspaces, diagnostics, and backup vaults all accumulate by default. Decide retention on purpose — the answer is a policy question ("do we need 2 years of these logs?"), and the default is usually not your policy.
- Disk SKUs. Premium SSD for a dev box's OS disk is a habit, not a requirement; standard SSD is dramatically cheaper and fine for most non-production use.
Win 5: question the architecture (effort: ongoing, opportunistic)
The deepest savings tier, listed last because it's the most work: some costs exist because a workload is shaped expensively, not because it's untidy. A VM running a small internal web app might be an App Service or container app at a fraction of the cost; a SQL Server VM licensed and patched by you might be a serverless database that pauses when idle; a file server VM might be Azure Files. Don't treat this as a migration mandate — re-architecture has real engineering cost and risk, and "leave it alone" is often the right call. But when a workload is being touched anyway (an upgrade, a rebuild, a new environment), asking "does this still need to be a VM?" at that moment is free, and it's how estates get structurally cheaper over years rather than just tidier.
The monthly cost review habit
Hygiene decays without cadence. The sustainable version for a small team is one recurring hour a month, with an agenda short enough to actually happen:
- Look at the trend line in Cost Analysis: this month versus the last three, grouped by service and by resource group. You're not auditing every line — you're looking for the shape of change.
- Explain every meaningful increase. New workload? Fine, note it. Nobody knows? That's the meeting's work item. Unexplained growth is the cost equivalent of config drift, and the same discipline applies: classify every change as expected or investigate.
- Check Advisor's cost tab and either act on or consciously dismiss its top items.
- Re-run the orphan sweep quarterly (it takes minutes once you've done it before).
- Glance at commitment coverage — are reservations/savings plans still matched to what actually runs?
Support the habit with automation that doesn't wait for the meeting: budgets with alert thresholds on every subscription (alerts at, say, 80% and 100% of expected spend — they cost nothing and catch runaway resources in days instead of at invoice time), and cost anomaly alerts for unusual spikes. Tag resources with an owner and an environment (env:dev etc.) as you go; every practice above gets easier when you can filter by tag, and "who owns this?" stops being archaeology.
The realistic outcome of all of the above for a typical small-team subscription that's never had a cost pass: 25–50% reduction, with the schedule and orphan work delivering most of it in the first month. None of it requires FinOps tooling, headcount, or negotiating skills — just the decision that the bill is something you read rather than something that happens to you.