# Deallocated Azure VM Residual Cost

> Deallocated standalone Azure VMs bill $0 for compute yet keep charging for attached managed disks and public IPs. Savings sum the priced monthly cost of those residual children, itemised into disk and IP components; the rule abstains when no child matches or every child is unpriced.

Source: https://zop.dev/integrations/azure/recommendations/deallocated-azure-vm-residual-cost
Updated: 2026-08-19

---

## Deallocated, standalone, and still billing children

Azure VM with Status = deallocated (compute billing stopped) and no ParentUID (standalone, not a VMSS member). The Azure analog of GCP RC-109 / AWS RC-001.
- resource.Status: must be deallocated (a merely stopped/not-deallocated VM still bills compute, so the residual-only basis does not apply).
- resource.ParentUID: empty (standalone).
- ResourceContextAware (SetResources) + PricingAware (SetPricing): the org resource set + per-UID monthly cost, to find and price the VM's residual children.
- Child association: managed disk already carries ParentUID = managedBy (the VM); public-ip carries ParentUID = VM via the discoverer's public-ip → NIC → VM ARG join (applyPublicIPLookupSets).

## Adding up the disks and public IPs left behind

concrete-or-abstain (Category orphan, exempt from shouldDropLowSavings). Compute is \$0 for a deallocated VM, so the deletable saving is the residual: Σ cost[child] over attached managed disks + public IPs (gated by the shared model.IsResidualCostChildType). CurrentCostUSD = SavingsUSD = residual, OptimizedCostUSD = 0. SavingsBreakdown itemises the residual into Managed disk + Public IP components (summing to SavingsUSD) for the UI. The child↔VM ParentUID match is case-insensitive (Azure returns the VM id and its children's cross-ref ids with divergent resourceGroup casing). The rule abstains when resources/pricing were not injected, no child matched, or every child is unpriced, and never emits a $0 or advisory rec. Disjoint from RC-1380 (RI/SP commitment, compute-domain) and idle_vm.go (running VMs only).

## Deleting the leftovers, or starting the VM

1. Check whether the VM is intentionally deallocated (e.g., a long-running batch worker).
2. If no longer needed, delete the VM, then its non-auto-delete managed disks.
3. Release/delete any Standard public IP associated with the VM (it bills while allocated).
4. If it should be running, start it (az vm start).
