How to Find Deleted Azure Resources Using Azure CLI and PowerShell

Accidentally deleted Azure resources can cause significant operational issues, particularly when administrators need to determine what was deleted, when it happened, and who performed the deletion.

Fortunately, Azure records management-plane operations such as resource creation, modification and deletion in the Azure Activity Log.

In this guide, we explain how to use Azure CLI from PowerShell to identify successfully deleted resources within an Azure subscription, determine who deleted them, export the information for auditing, and investigate deletions older than Azure's default Activity Log retention period.


What Is the Azure Activity Log?

The Azure Activity Log is a subscription-level log that records control-plane events performed against Azure resources.

Typical events include:

  • Creating a virtual machine

  • Deleting a network security group

  • Updating a storage account

  • Modifying Azure networking

  • Creating or deleting databases

  • Changing resource configuration

  • Performing administrative actions

This makes the Activity Log one of the first places to investigate when an Azure resource unexpectedly disappears.

Azure CLI provides the az monitor activity-log list command for querying Activity Log events.


Important: Azure Activity Log Retention Is 90 Days

Before attempting to search for deleted resources, it is important to understand Azure's retention period.

Azure Activity Log events are retained for 90 days by default. To retain Activity Log information beyond 90 days, organisations should export the logs through Diagnostic Settings to destinations such as:

  • Log Analytics Workspace

  • Azure Storage Account

  • Event Hub

Microsoft recommends exporting Activity Logs when longer-term retention or KQL-based querying is required.

Therefore, if you need to investigate the last 120 days, the most recent 90 days can normally be queried directly from the Activity Log.

The preceding 30 days will only be available if Activity Logs had already been exported to another destination.


Step 1 – Sign In to Azure

Open PowerShell and run:

az login

If your account has access to multiple Microsoft Entra tenants, specify the tenant:

az login --tenant "<TENANT-ID>"

You can then list all Azure subscriptions available to your account:

az account list `
    --query "[].{Name:name,SubscriptionId:id,State:state}" `
    -o table

Example:

Name                         SubscriptionId                         State
---------------------------  -------------------------------------  -------
Production Subscription      xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx   Enabled
Development Subscription     xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx   Enabled

Step 2 – Select the Azure Subscription

Set the subscription that you want to investigate.

$SubscriptionId = "<YOUR-SUBSCRIPTION-ID>"

az account set --subscription $SubscriptionId

Confirm the currently selected subscription:

az account show `
    --query "{Subscription:name,SubscriptionId:id,TenantId:tenantId}" `
    -o table

Always verify the selected subscription before performing an audit in environments where administrators have access to multiple Azure subscriptions.


Step 3 – Find Deleted Azure Resources

Use the following command to retrieve deletion operations from the available Activity Log history:

az monitor activity-log list `
    --subscription $SubscriptionId `
    --offset 90d `
    --max-events 10000 `
    --query "[?contains(operationName.value, '/delete')].[eventTimestamp, resourceGroupName, resourceId, operationName.value, caller, status.value]" `
    -o table

The command queries Activity Log events and looks for operations containing /delete.

Microsoft's Azure CLI supports filters including start time, end time, offset, caller, resource group, resource ID, correlation ID and operation status.

Typical output could look similar to:

EventTimestamp           ResourceGroup     ResourceId                         Operation                           Caller
-----------------------  ----------------  ---------------------------------  ----------------------------------  -------------------
2026-09-05T04:32:10Z     rg-production     /subscriptions/.../vm-server01     Microsoft.Compute/.../delete        admin@company.com

2026-08-29T02:11:35Z     rg-network        /subscriptions/.../nsg-prod        Microsoft.Network/.../delete        engineer@company.com

Step 4 – Show Only Successful Resource Deletions

Not every delete operation recorded in the Activity Log means that a resource was successfully removed.

Some deletion attempts might fail because of:

  • Resource locks

  • Azure Policy

  • Permission problems

  • Dependent resources

  • Resource state

  • Platform errors

For this reason, it is better to filter for operations where the status is Succeeded.

az monitor activity-log list `
    --subscription $SubscriptionId `
    --offset 90d `
    --max-events 10000 `
    --query "[?contains(operationName.value, '/delete') && status.value=='Succeeded'].[eventTimestamp, resourceGroupName, resourceId, operationName.value, caller]" `
    -o table

This provides a much cleaner list of resources that Azure reports as having been successfully deleted.


Step 5 – Use PowerShell to Analyse Deleted Resources

For larger environments, it is often easier to retrieve the Activity Log as JSON and analyse the results using PowerShell.

Run:

$logs = az monitor activity-log list `
    --subscription $SubscriptionId `
    --offset 90d `
    --max-events 10000 `
    -o json | ConvertFrom-Json

Now filter successfully completed deletion operations:

$deleted = $logs | Where-Object {
    $_.operationName.value -match "/delete$" -and
    $_.status.value -eq "Succeeded"
}

Display the results:

$deleted | Select-Object `
    eventTimestamp,
    resourceGroupName,
    resourceId,
    @{Name="Operation";Expression={$_.operationName.value}},
    caller,
    @{Name="Status";Expression={$_.status.value}} |
    Sort-Object eventTimestamp -Descending |
    Format-Table -AutoSize

This method makes it much easier to subsequently sort, filter, group or export the information.


Step 6 – Display Resource Name and Resource Type

A raw Azure Resource ID can be fairly long.

For example:

/subscriptions/xxxxxxxx/resourceGroups/RG-PROD/providers/Microsoft.Compute/virtualMachines/SQLVM01

We can convert the Activity Log information into a clearer PowerShell report.

$DeletedResources = $deleted | ForEach-Object {

    $resourceIdParts = $_.resourceId -split "/"

    [PSCustomObject]@{
        DeletedTime   = $_.eventTimestamp
        ResourceGroup = $_.resourceGroupName
        ResourceType  = $_.resourceType.value
        ResourceName  = $resourceIdParts[-1]
        ResourceId    = $_.resourceId
        DeletedBy     = $_.caller
        Operation     = $_.operationName.value
        Status        = $_.status.value
        CorrelationId = $_.correlationId
    }
}

Display the results:

$DeletedResources |
    Sort-Object DeletedTime -Descending |
    Format-Table `
        DeletedTime,
        ResourceGroup,
        ResourceType,
        ResourceName,
        DeletedBy `
        -AutoSize

A resulting report might look like:

DeletedTime           ResourceGroup   ResourceType                         ResourceName   DeletedBy
--------------------  --------------  -----------------------------------  -------------  -------------------
05/09/2026 04:32      rg-production   Microsoft.Compute/virtualMachines    SQLVM01        admin@company.com
02/09/2026 11:43      rg-network      Microsoft.Network/networkSecurityGroups nsg-prod    user@company.com
30/08/2026 08:02      rg-test         Microsoft.Network/publicIPAddresses  pip-test       engineer@company.com

Step 7 – Export Deleted Azure Resources to CSV

For audit, compliance or incident investigations, export the report to CSV.

$DeletedResources |
    Sort-Object DeletedTime -Descending |
    Export-Csv `
        ".\Azure-Deleted-Resources.csv" `
        -NoTypeInformation

The resulting file can be opened using Microsoft Excel:

Azure-Deleted-Resources.csv

This is useful when the deletion investigation needs to be shared with:

  • Management

  • Security teams

  • Infrastructure teams

  • Cloud governance teams

  • Auditors

  • Incident response teams


Step 8 – Find Who Deleted an Azure Resource

One of the most useful fields within the Azure Activity Log is the caller property.

Suppose an Azure VM called:

SQLVM01

was unexpectedly deleted.

Search for it using PowerShell:

$logs | Where-Object {
    $_.resourceId -match "SQLVM01" -and
    $_.operationName.value -match "/delete"
} | Select-Object `
    eventTimestamp,
    resourceId,
    caller,
    correlationId,
    operationId,
    @{Name="Operation";Expression={$_.operationName.value}},
    @{Name="Status";Expression={$_.status.value}} |
    Format-List

An example result might be:

eventTimestamp : 2026-09-02T11:35:42Z
resourceId     : /subscriptions/.../virtualMachines/SQLVM01
caller         : administrator@company.com
correlationId  : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
operationId    : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Operation      : Microsoft.Compute/virtualMachines/delete
Status         : Succeeded

The caller could represent a:

  • User

  • Service principal

  • Managed identity

  • Automation process

  • Azure service

For more complex investigations, the CorrelationId can also help identify related operations that occurred as part of the same activity.


Step 9 – Search for Deleted Virtual Machines

To display only VM deletions:

$deleted | Where-Object {
    $_.resourceId -match "/virtualMachines/"
} | Select-Object `
    eventTimestamp,
    resourceGroupName,
    resourceId,
    caller

This is particularly useful after an incident involving compute resources.


Step 10 – Search for Deleted Storage Accounts

$deleted | Where-Object {
    $_.resourceId -match "/storageAccounts/"
} | Select-Object `
    eventTimestamp,
    resourceGroupName,
    resourceId,
    caller

Step 11 – Search for Deleted Azure SQL Resources

$deleted | Where-Object {
    $_.resourceId -match "Microsoft.Sql"
} | Select-Object `
    eventTimestamp,
    resourceGroupName,
    resourceId,
    caller

This can help identify deleted:

  • Azure SQL Databases

  • Azure SQL logical servers

  • SQL Managed Instance-related resources

  • Other Microsoft.Sql resources


Step 12 – Search for Deleted Network Resources

$deleted | Where-Object {
    $_.resourceId -match "Microsoft.Network"
} | Select-Object `
    eventTimestamp,
    resourceGroupName,
    resourceId,
    caller

This can identify deletion operations involving resources such as:

  • Network Security Groups

  • Public IP addresses

  • Virtual networks

  • Subnets

  • Load balancers

  • Application Gateways

  • VPN Gateways

  • Route tables


Step 13 – Search a Specific Resource Group

If you already know which Resource Group contained the missing resource, filter the Activity Log directly.

az monitor activity-log list `
    --subscription $SubscriptionId `
    --resource-group "RG-PRODUCTION" `
    --offset 90d `
    --max-events 10000 `
    --query "[?contains(operationName.value, '/delete') && status.value=='Succeeded'].[eventTimestamp, resourceId, operationName.value, caller]" `
    -o table

This is faster and easier to analyse in subscriptions containing hundreds or thousands of resources.


Step 14 – Query a Specific 120-Day Period

PowerShell can calculate the start and end dates automatically:

$EndDate   = (Get-Date).ToUniversalTime()
$StartDate = $EndDate.AddDays(-120)

$StartTime = $StartDate.ToString("yyyy-MM-ddTHH:mm:ssZ")
$EndTime   = $EndDate.ToString("yyyy-MM-ddTHH:mm:ssZ")

Check the calculated dates:

Write-Host "Start: $StartTime"
Write-Host "End:   $EndTime"

Then query Azure:

az monitor activity-log list `
    --subscription $SubscriptionId `
    --start-time $StartTime `
    --end-time $EndTime `
    --max-events 10000 `
    -o json

However, specifying 120 days does not extend Azure's Activity Log retention.

If the underlying Activity Log only contains the default 90 days of history, Azure cannot return the additional 30 days.


How Do You Find Deletions Older Than 90 Days?

This is where Azure Diagnostic Settings and Log Analytics become important.

If Activity Logs were previously exported to a Log Analytics Workspace, older events may still exist there depending on the configured workspace retention.

Activity Log diagnostic settings operate at subscription level rather than Resource Group level.

Check the subscription's diagnostic settings:

az monitor diagnostic-settings subscription list `
    --subscription $SubscriptionId `
    -o table

For detailed output:

az monitor diagnostic-settings subscription list `
    --subscription $SubscriptionId `
    -o json

Look for a configuration sending Activity Logs to a Log Analytics Workspace.


Find Available Log Analytics Workspaces

Run:

az monitor log-analytics workspace list `
    --subscription $SubscriptionId `
    --query "[].{Name:name,ResourceGroup:resourceGroup,WorkspaceId:customerId}" `
    -o table

Activity Log entries exported to Log Analytics are available through the AzureActivity table.


Query 120 Days of Deleted Resources Using KQL

If Activity Logs were exported to Log Analytics during the period you need, run:

AzureActivity
| where TimeGenerated >= ago(120d)
| where OperationNameValue endswith "/delete"
| where ActivityStatusValue =~ "Succeeded"
| project
    TimeGenerated,
    ResourceGroup,
    ResourceProviderValue,
    ResourceId,
    OperationNameValue,
    Caller,
    ActivityStatusValue,
    CorrelationId
| order by TimeGenerated desc

This provides an excellent audit trail showing:

  • Deletion date and time

  • Resource Group

  • Azure Resource ID

  • Resource provider

  • Operation

  • User or identity responsible

  • Operation status

  • Correlation ID


Query Log Analytics from PowerShell Using Azure CLI

You can also execute the Log Analytics query directly from PowerShell.

First specify your workspace:

$WorkspaceId = "<LOG-ANALYTICS-WORKSPACE-ID>"

Then run:

az monitor log-analytics query `
    --workspace $WorkspaceId `
    --analytics-query "
AzureActivity
| where TimeGenerated >= ago(120d)
| where OperationNameValue endswith '/delete'
| where ActivityStatusValue =~ 'Succeeded'
| project TimeGenerated, ResourceGroup, ResourceId, OperationNameValue, Caller, CorrelationId
| order by TimeGenerated desc
" `
    -o table

This is typically the preferred solution when auditing historical deletions beyond the standard Activity Log window.


Recommended Azure Logging Configuration

Organisations should not rely exclusively on Azure's default Activity Log retention for audit and forensic investigations.

For production Azure subscriptions, consider configuring Diagnostic Settings to export the Activity Log to:

Log Analytics

Best when you need:

  • KQL queries

  • Azure Monitor integration

  • Microsoft Sentinel integration

  • Security investigations

  • Operational monitoring

  • Centralised log analysis

Azure Storage

Useful when the primary goal is:

  • Long-term archive

  • Compliance retention

  • Lower-cost storage

  • Historical evidence

Event Hub

Useful when logs need to be forwarded to:

  • SIEM platforms

  • Splunk

  • Third-party monitoring systems

  • Security analytics platforms

Azure diagnostic settings support exporting logs to destinations including Log Analytics, Event Hub and Storage.


Recommended Quick Audit Script

For most administrators investigating a recent deletion, the following script provides a good starting point:

$SubscriptionId = "<YOUR-SUBSCRIPTION-ID>"

az login

az account set --subscription $SubscriptionId

az monitor activity-log list `
    --subscription $SubscriptionId `
    --offset 90d `
    --max-events 10000 `
    --query "[?contains(operationName.value, '/delete') && status.value=='Succeeded'].[eventTimestamp, resourceGroupName, resourceType.value, resourceId, caller]" `
    -o table

This immediately provides:

  • When the deletion occurred

  • Which Resource Group was involved

  • Resource type

  • Full Resource ID

  • Identity that performed the operation


Security and Governance Considerations

Being able to identify who deleted a resource is useful after an incident, but preventing inappropriate deletion is even more important.

Production Azure environments should consider implementing:

Azure Resource Locks

Apply CanNotDelete locks to critical resources where appropriate.

Azure RBAC

Restrict deletion permissions according to the principle of least privilege.

Azure Policy

Use Azure Policy to enforce governance requirements across subscriptions and Resource Groups.

Activity Log Alerts

Create alerts for high-risk administrative operations.

Centralised Activity Log Collection

Export Activity Logs to Log Analytics or another central logging platform.

Microsoft Sentinel

For security-sensitive environments, activity logs can form part of a larger SIEM and incident-detection strategy.


Conclusion

Azure Activity Logs provide an effective way to investigate deleted Azure resources and answer three important questions:

What was deleted?

When was it deleted?

Who deleted it?

For recent incidents, Azure CLI and PowerShell provide a fast method of querying deletion activity directly from the subscription.

The most important limitation is retention.

Azure Activity Logs are retained for approximately 90 days by default.

If your organisation needs 120 days, one year or several years of audit history, Activity Logs should be proactively exported using Azure Diagnostic Settings to Log Analytics, Storage or another supported destination.

For business-critical Azure environments, long-term Activity Log collection should be considered part of the organisation's overall cloud security, governance and incident-response strategy.


Need Help Managing or Auditing Your Azure Environment?

Onsys Technologies provides Azure consulting, administration, cloud security, database and managed IT services for Australian organisations.

Our team can assist with:

  • Azure environment health checks

  • Azure monitoring and alerting

  • Log Analytics implementation

  • Cloud security assessments

  • Azure governance

  • Azure migration

  • Azure networking

  • Azure SQL and SQL Managed Instance

  • Microsoft SQL Server

  • Database managed services

  • Incident investigation and troubleshooting

Contact Onsys Technologies to discuss Azure administration, security, monitoring and managed cloud support.