---
cuppy_hub: azure
cuppy_path: reference/arm/throttling-and-long-running-operations.md
cuppy_section: docs
cuppy_doc: 1VD0-ZV4A
cuppy_doc_uuid: d4d522d1-2f1c-4239-ae28-f7ffdf04d7cc
cuppy_permalink: https://cuppy.io/azure/d/1VD0-ZV4A
cuppy_version: 1
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/azure/docs/reference/arm/throttling-and-long-running-operations
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: f51fe6ed987c43fb9f22dec50257fc84ca17b5df4dd759fcc9d641a8bc355ad0
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# Resource Manager throttling and long-running operations

## Throttling limits

Since 2024, Resource Manager throttles **per region** with a token bucket. A burst can spend the whole bucket; it then refills at a steady rate.

| Scope | Operation | Bucket | Refill per second |
|---|---|---|---|
| Subscription | reads | 250 | 25 |
| Subscription | writes | 200 | 10 |
| Subscription | deletes | 200 | 10 |
| Tenant | reads / writes / deletes | 250 / 200 / 200 | 25 / 10 / 10 |

- Subscription limits apply **per service principal and per operation type**. A global subscription limit is 15 times that, across all principals. One noisy identity throttles itself first.
- Free and trial subscriptions may get less.
- **Providers throttle separately**, per region of the resource: for example Microsoft.Network allows 1,000 writes and 10,000 reads per 5 minutes; Compute, Storage, Key Vault and Resource Graph have their own limits. Some providers return 429 for a temporary resource state, not volume.
- **Metrics reads** (`…/providers/microsoft.insights/metrics`) are a common cause of subscription throttling. Use the batch metrics API.

**What you get:** HTTP 429 with a `Retry-After` value in seconds. Requests sent before it elapses count against you. Remaining budget appears in response headers: `x-ms-ratelimit-remaining-subscription-reads`, `-writes`, `-deletes`, and the tenant variants. Background-job throttling looks different: `The request for subscription '…' could not be processed due to an excessive volume of traffic. Please try again later.`

## Retries in the TypeScript SDK

Every `@azure/*` client runs `defaultRetryPolicy` (`@azure/core-rest-pipeline` 1.25): it retries on 429 using `Retry-After`, on transport errors (DNS, resets), and otherwise with exponential backoff. **Defaults: 3 retries, starting at 1 second.** For batch scripts, raise it rather than writing your own loop:

```ts
import { DefaultAzureCredential } from "@azure/identity";
import { ResourceManagementClient } from "@azure/arm-resources";

const client = new ResourceManagementClient(new DefaultAzureCredential(), process.env.AZURE_SUBSCRIPTION_ID ?? "", {
  retryOptions: { maxRetries: 8, retryDelayInMs: 2000, maxRetryDelayInMs: 60000 },
});

// Reads in a loop are the usual throttle source: list once, not get per item.
for await (const rg of client.resourceGroups.list()) {
  console.log(rg.name, rg.location);
}
```

From the CLI, `az` retries too; for scripts, prefer one `az resource list` or Resource Graph query over hundreds of `show` calls.

## Long-running operations

A create, update or delete that can't finish at once returns **201 Created** or **202 Accepted** and a `provisioningState` that isn't terminal (`Succeeded`, `Failed` and `Canceled` are terminal). To follow it:

1. If the response has **`Azure-AsyncOperation`**, poll that URL. Its body carries the status.
2. Otherwise poll the **`Location`** URL until it stops returning 202.
3. Wait `Retry-After` seconds between polls when it's given. Accept status URLs of at least 4 KB.

**In the TypeScript SDK the poller does this.** In the 2026 packages (`@azure/arm-resourcesdeployments`, `@azure/arm-resources` 8), long-running methods return a `PollerLike` you can simply `await`; the older `begin…AndWait` helpers still exist but are marked deprecated:

```ts
import { DefaultAzureCredential } from "@azure/identity";
import { DeploymentsClient } from "@azure/arm-resourcesdeployments";

const deployments = new DeploymentsClient(new DefaultAzureCredential(), process.env.AZURE_SUBSCRIPTION_ID ?? "");

export async function deploy(resourceGroup: string, name: string, template: object) {
  const result = await deployments.deployments.createOrUpdate(resourceGroup, name, {
    properties: { mode: "Incremental", template },
  });
  return result.properties?.provisioningState; // terminal state
}
```

**CLI:** commands wait by default; `--no-wait` returns at once, and `az resource wait --ids <id> --created` (or `--updated`, `--deleted`, `--custom "<JMESPath>"`) waits later.

A terminal `Failed` carries the operation's error. For deployments, read the failed operations (`guides/arm/debug-failed-deployment.md`).


---
<!-- cuppy -->
You are reading one file. The same content is free over MCP at https://cuppy.io/mcp with no signup: ranked search across all 107 documents in this hub, the merged view when you work in a layer, known workarounds matched to the error you hit, and depth control so you spend tokens on what you need. Start with the `_hello` tool. How to connect: https://cuppy.io/azure/ Something wrong in this document? Report it with the `session feedback` tool on the same endpoint.
<!-- /cuppy -->
