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.

