Skip to content

Commit 49d3f5f

Browse files
authored
Merge pull request #262471 from davidsmatlak/ds-arg-update-throttle-guidance-20230104
Adds content about throttle support
2 parents 0bb56e8 + a97da07 commit 49d3f5f

1 file changed

Lines changed: 48 additions & 55 deletions

File tree

articles/governance/resource-graph/concepts/guidance-for-throttled-requests.md

Lines changed: 48 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
---
2-
title: Guidance for throttled requests
3-
description: Learn to group, stagger, paginate, and query in parallel to avoid requests being throttled by Azure Resource Graph.
2+
title: Guidance for throttled requests in Azure Resource Graph
3+
description: Learn to group, stagger, paginate, and query in parallel to avoid requests being throttled in Azure Resource Graph.
44
author: davidsmatlak
55
ms.author: davidsmatlak
6-
ms.date: 08/18/2022
6+
ms.date: 01/04/2024
77
ms.topic: conceptual
88
ms.custom: devx-track-csharp
99
---
10+
1011
# Guidance for throttled requests in Azure Resource Graph
1112

1213
When creating programmatic and frequent use of Azure Resource Graph data, consideration should be
13-
made for how throttling impacts the results of the queries. Changing the way data is requested can
14+
made for how throttling affects the results of the queries. Changing the way data is requested can
1415
help you and your organization avoid being throttled and maintain the flow of timely data about your
1516
Azure resources.
1617

1718
This article covers four areas and patterns related to the creation of queries in Azure Resource
1819
Graph:
1920

20-
- Understand throttling headers
21-
- Grouping queries
22-
- Staggering queries
23-
- The impact of pagination
21+
- Understand throttling headers.
22+
- Grouping queries.
23+
- Staggering queries.
24+
- The effect of pagination.
2425

2526
## Understand throttling headers
2627

@@ -42,20 +43,19 @@ first 10,000 subscriptions and the `x-ms-tenant-subscription-limit-hit` header i
4243
To illustrate how the headers work, let's look at a query response that has the header and values of
4344
`x-ms-user-quota-remaining: 10` and `x-ms-user-quota-resets-after: 00:00:03`.
4445

45-
- Within the next 3 seconds, at most 10 queries may be submitted without being throttled.
46-
- In 3 seconds, the values of `x-ms-user-quota-remaining` and `x-ms-user-quota-resets-after` will be
47-
reset to `15` and `00:00:05` respectively.
46+
- Within the next 3 seconds, at most 10 queries can be submitted without being throttled.
47+
- In 3 seconds, the values of `x-ms-user-quota-remaining` and `x-ms-user-quota-resets-after` are reset to `15` and `00:00:05` respectively.
4848

4949
To see an example of using the headers to _backoff_ on query requests, see the sample in
50-
[Query in Parallel](#query-in-parallel).
50+
[Query in parallel](#query-in-parallel).
5151

5252
## Grouping queries
5353

5454
Grouping queries by the subscription, resource group, or individual resource is more efficient than
5555
parallelizing queries. The quota cost of a larger query is often less than the quota cost of many
5656
small and targeted queries. The group size is recommended to be less than _300_.
5757

58-
- Example of a poorly optimized approach
58+
- Example of a poorly optimized approach.
5959

6060
```csharp
6161
// NOT RECOMMENDED
@@ -76,7 +76,7 @@ small and targeted queries. The group size is recommended to be less than _300_.
7676
}
7777
```
7878

79-
- Example #1 of an optimized grouping approach
79+
- Example of an optimized grouping approach.
8080

8181
```csharp
8282
// RECOMMENDED
@@ -99,7 +99,7 @@ small and targeted queries. The group size is recommended to be less than _300_.
9999
}
100100
```
101101

102-
- Example #2 of an optimized grouping approach for getting multiple resources in one query
102+
- Example of an optimized grouping approach for getting multiple resources in one query.
103103

104104
```kusto
105105
Resources | where id in~ ({resourceIdGroup}) | project name, type
@@ -129,22 +129,21 @@ small and targeted queries. The group size is recommended to be less than _300_.
129129

130130
## Staggering queries
131131

132-
Because of the way throttling is enforced, we recommend queries to be staggered. That is, instead of
133-
sending 60 queries at the same time, stagger the queries into four 5-second windows:
132+
Because of the way throttling is enforced, we recommend queries to be staggered. For example, instead of sending 60 queries at the same time, stagger the queries into four 5-second windows.
134133

135-
- Non-staggered query schedule
134+
- Nonstaggered query schedule.
136135

137136
| Query Count | 60 | 0 | 0 | 0 |
138137
|---------------------|-----|------|-------|-------|
139138
| Time Interval (sec) | 0-5 | 5-10 | 10-15 | 15-20 |
140139

141-
- Staggered query schedule
140+
- Staggered query schedule.
142141

143142
| Query Count | 15 | 15 | 15 | 15 |
144143
|---------------------|-----|------|-------|-------|
145144
| Time Interval (sec) | 0-5 | 5-10 | 10-15 | 15-20 |
146145

147-
Here's an example of respecting throttling headers when querying Azure Resource Graph:
146+
The following code is an example of respecting throttling headers when querying Azure Resource Graph.
148147

149148
```csharp
150149
while (/* Need to query more? */)
@@ -166,12 +165,11 @@ while (/* Need to query more? */)
166165
}
167166
```
168167

169-
### Query in Parallel
168+
### Query in parallel
170169

171170
Even though grouping is recommended over parallelization, there are times where queries can't be
172-
easily grouped. In these cases, you may want to query Azure Resource Graph by sending multiple
173-
queries in a parallel fashion. Here's an example of how to _backoff_ based on throttling headers
174-
in such scenarios:
171+
easily grouped. In these cases, you might want to query Azure Resource Graph by sending multiple
172+
queries in a parallel fashion. The following example shows how to _backoff_ based on throttling headers.
175173

176174
```csharp
177175
IEnumerable<IEnumerable<string>> queryGroup = /* Groups of queries */
@@ -205,44 +203,39 @@ async Task ExecuteQueries(IEnumerable<string> queries)
205203

206204
## Pagination
207205

208-
Since Azure Resource Graph returns at most 1,000 entries in a single query response, you may need to
209-
[paginate](./work-with-data.md#paging-results) your queries to get the complete dataset you're
210-
looking for. However, some Azure Resource Graph clients handle pagination differently than others.
211-
212-
- C# SDK
206+
Because Azure Resource Graph returns a maximum of 1,000 entries in a single query response, you might need to [paginate](./work-with-data.md#paging-results) your queries to get the complete dataset you want. But some Azure Resource Graph clients handle pagination differently than others.
213207

214-
When using ResourceGraph SDK, you need to handle pagination by passing the skip token being
215-
returned from the previous query response to the next paginated query. This design means you need
216-
to collect results from all paginated calls and combine them together at the end. In this case,
217-
each paginated query you send takes one query quota:
208+
When using ResourceGraph SDK, you need to handle pagination by passing the skip token being
209+
returned from the previous query response to the next paginated query. This design means you need
210+
to collect results from all paginated calls and combine them together at the end. In this case,
211+
each paginated query you send takes one query quota.
218212

219-
```csharp
220-
var results = new List<object>();
221-
var queryRequest = new QueryRequest(
222-
subscriptions: new[] { mySubscriptionId },
223-
query: "Resources | project id, name, type");
213+
```csharp
214+
var results = new List<object>();
215+
var queryRequest = new QueryRequest(
216+
subscriptions: new[] { mySubscriptionId },
217+
query: "Resources | project id, name, type");
218+
var azureOperationResponse = await this.resourceGraphClient
219+
.ResourcesWithHttpMessagesAsync(queryRequest, header)
220+
.ConfigureAwait(false);
221+
while (!string.IsNullOrEmpty(azureOperationResponse.Body.SkipToken))
222+
{
223+
queryRequest.Options ??= new QueryRequestOptions();
224+
queryRequest.Options.SkipToken = azureOperationResponse.Body.SkipToken;
224225
var azureOperationResponse = await this.resourceGraphClient
225-
.ResourcesWithHttpMessagesAsync(queryRequest, header)
226-
.ConfigureAwait(false);
227-
while (!string.IsNullOrEmpty(azureOperationResponse.Body.SkipToken))
228-
{
229-
queryRequest.Options ??= new QueryRequestOptions();
230-
queryRequest.Options.SkipToken = azureOperationResponse.Body.SkipToken;
231-
var azureOperationResponse = await this.resourceGraphClient
232-
.ResourcesWithHttpMessagesAsync(queryRequest, header)
233-
.ConfigureAwait(false);
234-
results.Add(azureOperationResponse.Body.Data.Rows);
226+
.ResourcesWithHttpMessagesAsync(queryRequest, header)
227+
.ConfigureAwait(false);
228+
results.Add(azureOperationResponse.Body.Data.Rows);
235229

236-
// Inspect throttling headers in query response and delay the next call if needed.
237-
}
238-
```
230+
// Inspect throttling headers in query response and delay the next call if needed.
231+
}
232+
```
239233

240-
## Still get throttled?
234+
## Still being throttled?
241235

242-
If you're getting throttled after exercising the above recommendations, contact the [Azure Resource
243-
Graph team](mailto:[email protected]).
236+
If you used this article's recommendations and your Azure Resource Graph queries are still being throttled, contact the [Azure Resource Graph team](mailto:[email protected]). The team supports Azure Resource Graph but doesn't support [Microsoft Graph throttling](/graph/throttling).
244237

245-
Provide these details:
238+
Provide these details when you contact the Azure Resource Graph team:
246239

247240
- Your specific use-case and business driver needs for a higher throttling limit.
248241
- How many resources do you have access to? How many of the are returned from a single query?

0 commit comments

Comments
 (0)