How to reduce cloud costs: the fixes that move the bill

Where the money goes, which fixes move it most, and the order to make them in, on Azure and AWS.

Published 21 October 2026 · By Udit Sharma (opens in a new tab), Sales engineer, Zoorik · Published by Zoorik

Short answer. Reduce cloud costs on Azure and AWS in this order. Tag every resource so you can see where the money goes. Then fix the architecture, remove what nothing uses, shrink Kubernetes requests so spare nodes can go, and bring disks back to the size of their data. Buy reservations or savings plans last, sized to the baseline that remains, because you pay for a commitment every hour, used or not.

How to reduce cloud costs: see the bill first, commit last

Picture a team that buys a one-year Azure savings plan, a fixed hourly spend sized to this month’s compute, then deallocates its development VMs every night and lets two spare nodes go. The plan still bills in full every hour, though part of the usage it was sized for is gone, and whatever an hour doesn’t use expires.

Take the ways to reduce cloud costs in order:

  1. See where the money goes.
  2. Fix the architecture.
  3. Remove what nothing uses.
  4. Reduce Kubernetes requests, then nodes.
  5. Bring disks back to the size of their data.
  6. Commit to the baseline that’s left.
A commitment bought before the fixes bills for usage that's gone Illustration with no measured figures. Two rows share one time axis, with a marker a third of the way along where the fixes land. In both rows the hourly usage, a step line, runs high before the marker and steps down after it. Commit first: the hourly commitment, a dashed line, runs the whole width at the floor of the usage before the fixes, so after the marker an amber band between it and the usage marks unused commitment, paid and then expired. Commit last: the hourly commitment starts soon after the marker at the floor of the reduced usage, usage fills it every hour, and there is no amber band. A commitment bought before the fixes bills for usage that's gone fixes landCommit firsthourly usagehourly commitmentunused commitment: paid, then expiresCommit lasthourly commitmentusage fills it every hourtime
Illustration, no measured figures: a savings plan bills its hourly commitment whether usage fills it or not.

First, find out who owns each line of the bill. Tags let Cost analysis in Microsoft Cost Management and AWS Cost Explorer split your spend by team, application and environment. On Azure, four rules decide whether and when a tag shows up:

  • Cost Management applies a tag only to usage while it’s on the resource.
  • A resource group’s tags reach its resources’ usage records only if you turn on tag inheritance.
  • Some resource types don’t carry tags into usage data at all.
  • Cost data arrives late: typically within 8 to 24 hours for Enterprise Agreement and Microsoft Customer Agreement subscriptions, and up to 72 hours for pay-as-you-go.

So tag first and analyze a few days later. A Kubernetes cluster appears on the bill as its machines, so splitting it by team needs a view from inside the cluster, which AKS cost analysis covers.

Managing cloud costs effectively needs standing rules, or the bill drifts back. For cloud governance to reduce costs, start with three: every resource carries the tags your reports group by, every subscription or account has a budget with an alert, and someone reads the biggest lines every month. Let those lines pick the fix that moves your bill most: VM compute points to architecture and idle VMs, cluster node VMs to Kubernetes, and disks to block storage.

Fix the architecture that sets the bill

An app on its own VM is sized for its own peak, and a running VM bills for that peak around the clock, so three apps on three VMs carry three peaks. A shared pool such as a Kubernetes cluster holds what its apps reserve. Once that follows each app’s demand, for example with the Horizontal Pod Autoscaler (HPA) adding and removing pods, the pool needs room only for the combined demand, which is smaller whenever the peaks don’t line up.

Three peaks that don't line up need less room on a shared pool Illustration with no measured figures. On the left, three VMs, one each for app A, app B and app C, each as tall as its app's own peak, stack up to the sum of the three peaks, which a dashed line marks as the capacity on own VMs. On the right, the same three apps share a pool over one day: three stacked bands, each peaking at a different hour, so the top edge of the stack is their combined demand. A second dashed line, touching the top of the stack at its highest point, marks the peak of the combined demand, the capacity a shared pool carries once what each app reserves follows its demand. The amber span between the two lines is the capacity the shared pool doesn't carry. Three peaks that don't line up need less room on a shared pool app Aapp Bapp Cthree VMsapp Aapp Bapp Ccapacity the shared pool doesn't carryown VMs:sum of the three peaksshared pool:peak of the combined demandone day
Illustration, no measured figures: a shared pool needs only the combined peak once what each app reserves follows its demand.

How poor architecture increases your cloud bill walks through the decisions that cost most, such as leaving development and test environments running all day. Architecture changes need a pilot, so start them early and run the quicker fixes below alongside.

Remove what nothing uses

A VM that looks off can still bill. Azure bills a VM in the Stopped state, also called Stopped (allocated), for instance usage, and that’s where a shutdown from inside the guest OS leaves it. Only a deallocated VM, shown as Stopped (deallocated), has released the hardware and stopped that charge. In the Azure CLI, az vm stop keeps the compute resources and az vm deallocate releases them. A deallocated VM still pays for its disks and networking.

Only deallocation takes the idle hours off the instance charge One week of 168 hours, Monday to Sunday, drawn twice on one shared axis. In both rows the VM runs 10 hours a day on the 5 weekdays, 50 hours in all. Shut down inside the guest OS: the other 118 hours are Stopped (allocated) and the instance is still billed, so the billed instance hours are 168. Deallocated: the other 118 hours are Stopped (deallocated) with no instance charge, so the billed instance hours are 50. Only deallocation takes the idle hours off the instance charge one week, 168 hMonTueWedThuFriSatSunbilled instance hoursShut down inside the guest OS168 hrunning: 50 hStopped (allocated): 118 h, instance still billedDeallocated50 hStopped (deallocated): 118 h, no instance charge
In its 118 deallocated hours the VM still pays for its disks and networking.

Then the leftovers: disks and snapshots of deleted VMs. Finding unattached disks in Azure shows how to list the disks, and the snapshot guides for Azure and Amazon Elastic Block Store (EBS) explain what a snapshot bills for. Deleting a disk deletes its data, so confirm the owner from its tags before you remove it.

Reduce Kubernetes requests, then nodes

In Kubernetes, a request is the CPU and memory a container asks the cluster to set aside for it. A request set for a worst case that never comes holds node capacity that nothing uses, and no node autoscaler will give it back.

Node autoscalers such as the Cluster Autoscaler and Karpenter add nodes until every pod’s requests fit and remove underused nodes. The Kubernetes documentation says this removal (consolidation), like provisioning, considers only Pod requests and not real usage.

The fix has two steps:

  1. Bring each container’s requests close to what it uses, from its own usage history, with headroom for its peaks. Kubernetes pod right sizing shows how, and Kubernetes overprovisioning shows where the extra tends to sit.
  2. Let the nodes go. Once smaller requests give a node’s pods room elsewhere, the autoscaler can drain the node and remove it. If a node stays, Cluster Autoscaler not scaling down lists what holds a node in place and what releases it.

VPA vs HPA covers how requests and the HPA meet on CPU, and How to reduce Kubernetes cost is the full walk-through for AKS and EKS.

Bring block storage back to the size of its data

Space bought for a migration or a one-off import stays on the bill after the data has gone. Block storage bills for the space you provision, and the size only goes one way. Microsoft Learn says shrinking an existing managed disk “isn’t supported and might result in data loss.” EBS Elastic Volumes can increase a volume’s size, change its type or adjust its performance, but can’t decrease its size.

Start by comparing used with provisioned space on every disk, on Azure VMs and on EBS. Some fixes need no copy. On an instance that supports Elastic Volumes, a type change runs while the volume stays attached, which makes a move from gp2 to gp3 a small job. On Azure, every Premium SSD v2 includes 3,000 IOPS and 125 MB/s at no charge, so compare it with Premium SSD before you resize.

Making a disk smaller is the hard part. You copy the data to a new, smaller disk and switch the mount over, which stops the services that use it. Can you shrink an Azure managed disk? and how to shrink an EBS volume walk through it.

Commit to the baseline that’s left

Reservations and savings plans reduce cloud computing costs through the price per hour, not the amount you use. Savings plans on both clouds run for one or three years. AWS Savings Plans trade a commitment to an amount of compute, measured per hour, for savings of up to 72% on compute. An Azure savings plan is a fixed hourly spend: each hour, Azure applies it to eligible usage, bills anything beyond it at pay-as-you-go rates, and lets the rest expire without rolling over. Azure savings plans can’t be canceled or refunded, and the one for compute doesn’t cover storage.

So measure the steady usage the steps above leave, and commit to that floor. Azure Advisor recommends a savings plan commitment from your eligible on-demand usage, and AWS Cost Explorer shows a recommended Savings Plans commitment. Before you act on either, wait until the usage behind it comes from after your last fix.

Where Coral and Amoeba fit

Two of these steps, requests and disks, never finish, because usage keeps moving.

Coral optimizes Kubernetes on AKS and EKS:

  • Requests: it rebalances each container’s CPU and memory requests to what it uses, once you switch on “Automatically optimize” for a policy or a workload.
  • Nodes: from install, it drains spare nodes one at a time, on the node pools you choose, so your Cluster Autoscaler, Karpenter or AKS node auto-provisioning (NAP) can remove them. Coral never adds nodes for demand. Pools that Karpenter or NAP already consolidate are left to them.
  • Disruption: pods resize in place on nodes running Kubernetes 1.33 or later, or restart one at a time within their PodDisruptionBudgets. When Coral drains a node, an eligible Deployment or Argo Rollout gets a warm handover, even with one replica: a new copy is Ready on another node before the old pod goes. Any other app with a single copy restarts when it moves.

On our own AKS development cluster, Coral removed a spare 4-CPU worker on its own, rebalanced the requests of 14 apps, and swapped the remaining worker for a cheaper machine of the same size. Eight days after we connected it, the cluster’s machines cost $154.76 a month instead of $368.65 at Azure list prices, 58% less. None of its single-copy apps qualified for a warm handover, so during the swap each restarted once and was back up within 5 to 82 seconds. Coral prices each saving at list price and leaves discounts, reservations and savings plans out, so check its figures against your own rates before you size a commitment.

Amoeba optimizes block storage on Azure managed disks and Amazon EBS. It moves a Windows or Linux VM’s data disks onto one pool sized to the data, holds it 80% to 90% full by default, and rightsizes it one disk at a time. On Linux, the systemd services that use the data mounts restart at the switch onto the pool, and every resize after it runs without unmounting. We estimate it takes 50–60% off block storage cost. It is an estimated range, not a promise. Amoeba is in early access, and the free block storage assessment works out your own figure.

Every Learn article, by subject

Sources: Microsoft Learn, “Understand Cost Management data” (opens in a new tab); Microsoft Learn, “States and billing status - Azure Virtual Machines” (opens in a new tab); Kubernetes, “Node Autoscaling” (opens in a new tab); Microsoft Learn, “Understand Azure Disk Storage billing” (opens in a new tab); Microsoft Learn, “Expand Virtual Hard Disks on a Linux VM” (opens in a new tab); AWS, “Modify an Amazon EBS volume using Elastic Volumes operations” (opens in a new tab); AWS, “What are Savings Plans?” (opens in a new tab); Microsoft Learn, “What are savings plans?” (opens in a new tab).

Find your own number

One line in your cloud console. One PDF report with your estimated saving at list price.

Estimate your saving

Talk to the builders

Thirty minutes with the people who build Coral.

Book a demo (opens in a new tab)

Or write to founders@zoorik.com