Understanding the Azure Resource Graph query language

The query language for the Azure Resource Graph supports a number of operators and functions. Each work and operate based on Kusto Query Language (KQL). To learn about the query language used by Resource Graph, start with the tutorial for KQL.

This article covers the language components supported by Resource Graph:

Resource Graph tables

Resource Graph provides several tables for the data it stores about Azure Resource Manager resource types and their properties. These tables can be used with join or union operators to get properties from related resource types. Here is the list of tables available in Resource Graph:

Resource Graph tables Description
Resources The default table if none defined in the query. Most Resource Manager resource types and properties are here.
ResourceContainers Includes subscription (in preview -- Microsoft.Resources/subscriptions) and resource group (Microsoft.Resources/subscriptions/resourcegroups) resource types and data.
AdvisorResources Includes resources related to Microsoft.Advisor.
AlertsManagementResources Includes resources related to Microsoft.AlertsManagement.
GuestConfigurationResources Includes resources related to Microsoft.GuestConfiguration.
HealthResources Includes resources related to Microsoft.ResourceHealth.
MaintenanceResources Includes resources related to Microsoft.Maintenance.
SecurityResources Includes resources related to Microsoft.Security.

For a complete list including resource types, see Reference: Supported tables and resource types.


Resources is the default table. While querying the Resources table, it isn't required to provide the table name unless join or union are used. However, the recommended practice is to always include the initial table in the query.

Use Resource Graph Explorer in the portal to discover what resource types are available in each table. As an alternative, use a query such as <tableName> | distinct type to get a list of resource types the given Resource Graph table supports that exist in your environment.

The following query shows a simple join. The query result blends the columns together and any duplicate column names from the joined table, ResourceContainers in this example, are appended with 1. As ResourceContainers table has types for both subscriptions and resource groups, either type might be used to join to the resource from resources table.

| join ResourceContainers on subscriptionId
| limit 1

The following query shows a more complex use of join. The query limits the joined table to subscriptions resources and with project to include only the original field subscriptionId and the name field renamed to SubName. The field rename avoids join adding it as name1 since the field already exists in Resources. The original table is filtered with where and the following project includes columns from both tables. The query result is a single key vault displaying type, the name of the key vault, and the name of the subscription it's in.

| where type == 'microsoft.keyvault/vaults'
| join (ResourceContainers | where type=='microsoft.resources/subscriptions' | project SubName=name, subscriptionId) on subscriptionId
| project type, name, SubName
| limit 1


When limiting the join results with project, the property used by join to relate the two tables, subscriptionId in the above example, must be included in project.

Extended properties (preview)

As a preview feature, some of the resource types in Resource Graph have additional type-related properties available to query beyond the properties provided by Azure Resource Manager. This set of values, known as extended properties, exists on a supported resource type in properties.extended. To see which resource types have extended properties, use the following query:

| where isnotnull(properties.extended)
| distinct type
| order by type asc

Example: Get count of virtual machines by instanceView.powerState.code:

| where type == 'microsoft.compute/virtualmachines'
| summarize count() by tostring(properties.extended.instanceView.powerState.code)

Resource Graph custom language elements

Shared query syntax (preview)

As a preview feature, a shared query can be accessed directly in a Resource Graph query. This scenario makes it possible to create standard queries as shared queries and reuse them. To call a shared query inside a Resource Graph query, use the {{shared-query-uri}} syntax. The URI of the shared query is the Resource ID of the shared query on the Settings page for that query. In this example, our shared query URI is /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/SharedQueries/providers/Microsoft.ResourceGraph/queries/Count VMs by OS. This URI points to the subscription, resource group, and full name of the shared query we want to reference in another query. This query is the same as the one created in Tutorial: Create and share a query.


You can't save a query that references a shared query as a shared query.

Example 1: Use only the shared query

The results of this Resource Graph query are the same as the query stored in the shared query.

{{/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/SharedQueries/providers/Microsoft.ResourceGraph/queries/Count VMs by OS}}

Example 2: Include the shared query as part of a larger query

This query first uses the shared query, and then uses limit to further restrict the results.

{{/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/SharedQueries/providers/Microsoft.ResourceGraph/queries/Count VMs by OS}}
| where properties_storageProfile_osDisk_osType =~ 'Windows'

Supported KQL language elements

Resource Graph supports a subset of KQL data types, scalar functions, scalar operators, and aggregation functions. Specific tabular operators are supported by Resource Graph, some of which have different behaviors.

Supported tabular/top level operators

Here is the list of KQL tabular operators supported by Resource Graph with specific samples:

KQL Resource Graph sample query Notes
count Count key vaults
distinct Show distinct values for a specific alias
extend Count virtual machines by OS type
join Key vault with subscription name Join flavors supported: innerunique, inner, leftouter. Limit of 3 join in a single query. Custom join strategies, such as broadcast join, aren't allowed. May be used within a single table or between the Resources and ResourceContainers tables.
limit List all public IP addresses Synonym of take. Doesn't work with Skip.
mvexpand Legacy operator, use mv-expand instead. RowLimit max of 400. The default is 128.
mv-expand List Cosmos DB with specific write locations RowLimit max of 400. The default is 128.
order List resources sorted by name Synonym of sort
project List resources sorted by name
project-away Remove columns from results
sort List resources sorted by name Synonym of order
summarize Count Azure resources Simplified first page only
take List all public IP addresses Synonym of limit. Doesn't work with Skip.
top Show first five virtual machines by name and their OS type
union Combine results from two queries into a single result Single table allowed: T | union [kind= inner|outer] [withsource=ColumnName] Table. Limit of 3 union legs in a single query. Fuzzy resolution of union leg tables isn't allowed. May be used within a single table or between the Resources and ResourceContainers tables.
where Show resources that contain storage

Query scope

The scope of the subscriptions from which resources are returned by a query depend on the method of accessing Resource Graph. Azure CLI and Azure PowerShell populate the list of subscriptions to include in the request based on the context of the authorized user. The list of subscriptions can be manually defined for each with the subscriptions and Subscription parameters, respectively. In REST API and all other SDKs, the list of subscriptions to include resources from must be explicitly defined as part of the request.

As a preview, REST API version 2020-04-01-preview adds a property to scope the query to a management group. This preview API also makes the subscription property optional. If a management group or a subscription list isn't defined, the query scope is all resources, which includes Azure Lighthouse delegated resources, that the authenticated user can access. The new managementGroupId property takes the management group ID, which is different from the name of the management group. When managementGroupId is specified, resources from the first 5000 subscriptions in or under the specified management group hierarchy are included. managementGroupId can't be used at the same time as subscriptions.

Example: Query all resources within the hierarchy of the management group named 'My Management Group' with ID 'myMG'.


    POST https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2020-04-01-preview
  • Request Body

        "query": "Resources | summarize count()",
        "managementGroupId": "myMG"

Escape characters

Some property names, such as those that include a . or $, must be wrapped or escaped in the query or the property name is interpreted incorrectly and doesn't provide the expected results.

  • . - Wrap the property name as such: ['propertyname.withaperiod']

    Example query that wraps the property odata.type:

    where type=~'Microsoft.Insights/alertRules' | project name, properties.condition.['odata.type']
  • $ - Escape the character in the property name. The escape character used depends on the shell Resource Graph is run from.

    • bash - \

      Example query that escapes the property $type in bash:

      where type=~'Microsoft.Insights/alertRules' | project name, properties.condition.\$type
    • cmd - Don't escape the $ character.

    • PowerShell - `

      Example query that escapes the property $type in PowerShell:

      where type=~'Microsoft.Insights/alertRules' | project name, properties.condition.`$type

Next steps