Azure governance

How to find recent resource changes in Azure

Find recent resource changes with Azure PowerShell and Resource Graph, filter Change Analysis in the Azure portal, or run Altivane's Azure Resource Changes report for who changed what.

By the Published

To find recent resource changes in Azure, query the resourcechanges table in Azure Resource Graph for each change's time, type, who made it and the properties it changed. Changes can be queried for 14 days, and only changes made through Azure Resource Manager are recorded, not data written inside a resource.

Choose the method that fits the job
MethodBest fit
PowerShellA CSV of every change in the last 7 days across your enabled subscriptions.
Admin centreA quick look at the changes behind an incident, grouped and filtered as you need.
AltivaneRecommended for change reviews, with each change's old and new values in a workbook.

Before you start

Use an account with read access to the subscriptions, such as the Reader role: Resource Graph returns nothing for resources you can't read. Change Analysis in Resource Graph costs nothing extra and needs no setup. A change record is usually there in less than 5 minutes, and some of its details can arrive before others.

Know what is left out. Resource Graph doesn't see changes made through a resource's own data API, such as writing to a table in a storage account, or file and configuration changes in App Service. A created or deleted resource has a record with no changed properties, and a property that appears with a new API version isn't shown as a change. The examples read and export; they change nothing. The script's finally block disconnects the account and clears its saved Azure contexts.

Option 1

Find recent resource changes with PowerShell

Install the modules once. The script queries Resource Graph across the enabled subscriptions, follows every page of results, and saves 1 row for each change.

PowerShell
Install-Module -Name Az.Accounts, Az.ResourceGraph -Repository PSGallery -Scope CurrentUser
PowerShell
$ErrorActionPreference = 'Stop'
Connect-AzAccount -ErrorAction Stop
try {
    $subscriptionIds = @(
        Get-AzSubscription | Where-Object State -eq 'Enabled' | Select-Object -ExpandProperty Id
    )
    if ($subscriptionIds.Count -eq 0) {
        Write-Output 'No enabled subscriptions are available to this account.'
        return
    }
    $query = @(
        'resourcechanges'
        '| extend changeTime = todatetime(properties.changeAttributes.timestamp)'
        '| where changeTime > ago(7d)'
        '| project id, changeTime, subscriptionId,'
        'changeType = tostring(properties.changeType),'
        'resourceId = tostring(properties.targetResourceId),'
        'resourceType = tostring(properties.targetResourceType),'
        'changedBy = tostring(properties.changeAttributes.changedBy),'
        'clientType = tostring(properties.changeAttributes.clientType),'
        'changes = properties.changes'
        '| order by id asc'
    ) -join ' '
    $rows = [System.Collections.Generic.List[object]]::new()
    $skipToken = $null
    do {
        $arguments = @{ Query = $query; Subscription = $subscriptionIds; First = 1000 }
        if ($skipToken) { $arguments.SkipToken = $skipToken }
        $page = Search-AzGraph @arguments
        foreach ($record in $page.Data) { $rows.Add($record) }
        $skipToken = $page.SkipToken
    } while ($skipToken)
    if ($rows.Count -eq 0) {
        Write-Output 'No resource changes were recorded in the last 7 days.'
    } else {
        $rows | Sort-Object changeTime -Descending | ForEach-Object {
            [pscustomobject]@{
                When              = $_.changeTime
                Change            = $_.changeType
                ResourceType      = $_.resourceType
                ChangedBy         = $_.changedBy
                Client            = $_.clientType
                ChangedProperties = @($_.changes.PSObject.Properties.Name) -join '; '
                SubscriptionId    = $_.subscriptionId
                ResourceId        = $_.resourceId
            }
        } | Export-Csv -Path './resource-changes.csv' -NoTypeInformation -Encoding utf8
        Write-Output "$($rows.Count) changes saved to resource-changes.csv."
    }
} finally {
    Disconnect-AzAccount | Out-Null
}

The CSV holds each change's time, whether it created, updated or deleted the resource, who made it, the client they used and the names of the properties it changed. Change ago(7d) to ago(14d) for everything Resource Graph keeps, or add '| where changeType == "Delete"' before the order by line for deletions alone. Resource Graph paging needs id in the results, so keep it if you edit the query.

Option 2

Review changes in Change Analysis in the Azure portal

  1. Sign in to the Azure portal with an account that can read the subscriptions.
  2. Search for Change Analysis and open it.
  3. Set Subscription, Resource group and Time span, and use Change types to keep creations, updates or deletions.
  4. Select Add filter to narrow by resource type, resource name or who made the change, and use Group by to group the results, such as by Changed By.

Change Analysis suits a look at what changed around 1 incident. For a file to keep and compare each week, use PowerShell or Altivane.

Common questions

Why does a new resource show no changed properties?

Azure records 0 changed properties for a creation, since every property is new, and for a deletion, since none remain. The record still says when it happened and who made it.

What do Unknown, Unspecified and System mean?

Unknown is a client Azure didn't recognise. Unspecified means the change carried no identity or client information. System is a background platform change that no person or app started directly.

How do I see changes older than 14 days?

Resource Graph keeps changes for 14 days. The activity log keeps operations for 90 days, with who ran each but not the properties changed. See how to export the activity log in Azure.

Microsoft references

Technical references checked on 7 November 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.

Talk to us about Altivane

Questions, or pricing? Get in touch.

Contact us