Orphaned snapshots: the basics
Why does a snapshot keep charging after its disk is gone?
A managed disk snapshot is an independent, point-in-time copy of a disk, stored as its own resource that bills by the gigabyte every month. It is deliberately decoupled from the disk it was taken from: deleting the source disk, or the virtual machine that owned it, does not delete the snapshots. That independence is the whole point during a migration or a restore, but it is also how a subscription ends up paying, month after month, for snapshots of disks that no longer exist and will never be restored.
These are orphaned snapshots: their 'sourceResourceId' points at a disk that has since been deleted. The disk is gone, the VM is gone, often the whole workload is gone, and yet the snapshot quietly keeps appearing on the bill. Nothing in Azure cleans them up for you, because Azure cannot know whether a given snapshot is dead weight or the one archived copy you are deliberately keeping for compliance. The Azure Cost Optimization workbook, available in the Advisor gallery, surfaces exactly this case in its Storage tab as the 'Snapshots with deleted source disk' query.
The work is small and almost always safe. You list every snapshot in the subscription, check which ones have a source disk that still exists, separate any that are intentional archives, and delete the rest. Each snapshot is a single resource with a single delete call, the saving starts the moment it is gone, and because the source disk has already been deleted there is rarely anything live depending on it.
In this lesson you will learn what makes an Azure disk snapshot orphaned, how to find every snapshot in a subscription whose source disk has been deleted, how to tell a deliberate archive from pure waste, and how to delete the waste safely and keep it from coming back. The grounding is the 'Snapshots with deleted source disk' query in the Azure Cost Optimization workbook's Storage tab.
The backup that outlived its data
Azure deliberately keeps snapshots alive when you delete their source disk, and the same is true when you delete the virtual machine: by default the OS and data disks, and any snapshots taken from them, all survive the VM. The design is a safety net, deletion should never quietly take your last copy of something, but it means the most common way an orphaned snapshot is born is a VM being torn down at the end of a project while its snapshots are left behind. Years later they can still be on the bill, point-in-time copies of a disk that was deleted long ago, faithfully preserved by a platform doing exactly what it was told.
Finding orphaned snapshots across a subscription
Priya is the platform engineer doing a quarterly cost sweep after the workbook's Storage tab flagged a cluster of snapshots whose source disk had been deleted, mostly left over from projects that wound down last year.
Rather than open each snapshot in the portal, Priya runs an Azure Resource Graph query that lists every snapshot in the subscription and joins it back to the disks that still exist, so the ones pointing at a deleted disk fall straight out.
Use Resource Graph to list every snapshot whose source disk no longer exists. The left-outer join keeps snapshots that found no matching disk.
The join leaves only snapshots whose source disk is gone. Most are dead weight; treat anything named or tagged like an archive as a deliberate keep until you confirm.
How you prove a snapshot is orphaneddeep dive
Every managed disk snapshot records where it came from in 'properties.creationData.sourceResourceId', the ARM resource id of the disk it was taken from. A snapshot is orphaned when that id points at a disk that no longer exists. You cannot tell this from the snapshot alone, because the field still holds the id of the deleted disk; you have to compare it against the set of disks that currently exist and keep the snapshots with no match. That comparison is exactly what the Cost Optimization workbook's 'Snapshots with deleted source disk' tile does, and what the Resource Graph join in this lesson reproduces.
Two details matter for accuracy. First, the join must be case-insensitive: ARM resource ids are not case-stable across services, so comparing the raw strings can wrongly flag a live snapshot as orphaned. Normalising both sides to lower case before the join, as the query does, avoids that. Second, a snapshot can legitimately have an empty source id, for example one imported from a blob, so the query keeps only snapshots that had a source disk id and found no matching disk, rather than treating every unmatched row as waste.
Orphaned status is also not the same as old or unused. A snapshot can be days old and already orphaned because its disk was deleted, or years old and perfectly valid because its disk is still in service. The workbook keeps these as separate tiles, 'Disk Snapshots with + 30 Days' for age and 'Snapshots with deleted source disk' for orphaned, precisely because they answer different questions. This lesson is about the orphaned case: the source is gone, so the only question left is whether you are keeping the snapshot on purpose.
What is the impact of leaving orphaned snapshots in place?
The direct impact is recurring spend with no return. Each orphaned snapshot bills for its used data every month for as long as it exists, and because the source disk is already deleted, that spend buys nothing: there is no live disk to restore from it and, in most cases, no workload it relates to any more. Left alone, the set only grows, because every migration, VM teardown and project wind-down can leave fresh snapshots behind, and nothing in Azure removes them.
The second-order impact is drag on every cost conversation. Orphaned snapshots inflate the storage line, blur the true cost of the workloads that are still running, and make right-sizing and showback harder because spend is attributed to copies of things that no longer exist. A subscription that quietly carries dead backups is one where nobody can fully trust the storage number.
There is no offsetting benefit to weigh. Unlike most cost decisions, where trimming spend risks performance or resilience, removing an orphaned snapshot costs you nothing you are using: the disk it protected is gone. The only thing standing between the estate and the saving is the work of finding them and confirming none is a deliberate archive.
How do you clear orphaned snapshots safely?
Treat this as one loop: find, confirm, delete, then prevent. The confirm step is the only one that needs judgement, because the goal is to delete every orphaned snapshot except the ones you are keeping on purpose.
1. Find every snapshot whose source disk is gone
Run the Resource Graph query, or open the workbook's 'Snapshots with deleted source disk' tile, to list every snapshot whose source disk no longer exists. Export the list with each snapshot's used size and resource group so the saving can be totalled and the work can be tracked.
2. Separate deliberate archives from waste
A snapshot orphaned on purpose, a retained copy kept after its source was decommissioned for compliance or rollback, is a retention decision, not waste. Identify these by tag, name or owner, record why each is kept, and exclude them. Everything else, the OS and data snapshots left behind by torn-down VMs and closed projects, is recoverable.
3. Delete the waste, capturing the saving immediately
Delete each confirmed-orphaned snapshot. Billing stops as soon as the snapshot is gone, so the saving begins this month, not next term. Because the source disk is already deleted, there is rarely anything live to break. If you want a final safety margin on a large or uncertain snapshot, export it to a blob first, but for the bulk of leftover project snapshots a straight delete is appropriate.
4. Stop it coming back
Put the workbook check on a quarterly cadence and assign a policy that requires an owner and an expiry tag on new snapshots, so future orphans are attributable and time-boxed rather than silently permanent. Look the policy up by exact display name at assignment time rather than hardcoding a definition id, since built-in tagging policy ids differ by tenant and version.
# 1. Find every snapshot whose source disk no longer exists (subscription-wide).
orphans=$(az graph query -q "resources \
| where type =~ 'microsoft.compute/snapshots' \
| extend src = tolower(tostring(properties.creationData.sourceResourceId)) \
| join kind=leftouter ( \
resources \
| where type =~ 'microsoft.compute/disks' \
| extend src = tolower(id) \
| project src, diskExists = id \
) on src \
| where isnull(diskExists) and isnotempty(src) \
| project id" \
--query "data[].id" -o tsv)
# 2. Review the list, then exclude any deliberate archives (here: a 'keep=archive' tag).
for id in $orphans; do
keep=$(az snapshot show --ids "$id" --query "tags.keep" -o tsv)
if [ "$keep" = "archive" ]; then
echo "SKIP (retained archive): $id"
continue
fi
# 3. Delete the orphaned snapshot. Billing stops immediately.
az snapshot delete --ids "$id"
echo "DELETED: $id"
done
# 4. Prevent recurrence: require an owner tag on new snapshots (look the policy up by name).
pid=$(az policy definition list \
--query "[?displayName=='Require a tag on resources'].name" -o tsv)
az policy assignment create \
--name require-owner-on-snapshots \
--policy "$pid" \
--params '{"tagName":{"value":"owner"}}' \
--scope "/subscriptions/<subscription-id>" Quick quiz
Question 1 of 5What makes an Azure managed disk snapshot 'orphaned'?
You scored
0 / 5
Keep learning
Go deeper on how Azure disk snapshots are billed, how to find them, and how to keep storage spend optimised.
- Cost Optimization workbook - Azure Advisor The Storage tab, including the 'Snapshots with deleted source disk' query this lesson is grounded in.
- Understand Azure Disk Storage billing How full and incremental snapshots are charged by used size per GB per month.
- Create an incremental snapshot of a managed disk Why incremental snapshots are cheaper and how 'creationData.sourceResourceId' records the source disk.
You can now treat orphaned snapshots as a clean, recurring saving rather than invisible drag: find every snapshot whose source disk has been deleted, separate the deliberate archives, delete the rest to stop the billing immediately, and put the workbook check on a cadence so the leak stays closed. The grounding is the 'Snapshots with deleted source disk' query in the Cost Optimization workbook's Storage tab.
Back to the library