Forty seconds into the production rollout the pipeline turns red: QuotaExceeded — Operation could not be completed as it results in exceeding approved standardDSv5Family Cores quota. Additional details - Current Limit: 24, Current Usage: 20, Additional Required: 8 (Minimum: 28). Submit a request for Quota increase. Nothing is wrong with your Bicep. The VM size is valid, the image exists, the region is right. You have simply run into a vCPU quota — a per-subscription, per-region ceiling Azure places on how many processor cores you may allocate from a given VM size family — and the default ceiling for that family in that region was smaller than your production footprint. This is one of the most common ways an Azure deployment fails, and it bites at the worst possible moment: at scale-out, in production, under a deadline.
The maddening part is that the number you hit is rarely the number you think you hit. Azure enforces vCPU limits at three stacked layers — a Total Regional vCPUs ceiling for the whole region, a per-family vCPUs ceiling for each size family (standardDSv5Family, standardFSv2Family, …), and a separate Spot vCPUs ceiling for evictable capacity — and your deployment must fit under every layer that applies. A request can pass the family quota and still die against the regional total; it can pass both and still fail because the specific SKU isn’t offered in your zone. Knowing which ceiling (or which other limit entirely) blocked you is the whole game, because each fix is different: raise the family quota, raise the regional total, pick another family, or move the workload.
This is the troubleshooting playbook for that whole class of failure. You will read your usage-versus-limit for every vCPU dimension before it bites, localise any QuotaExceeded / SkuNotAvailable / OperationNotAllowed to the exact ceiling that stopped it with the command that confirms it and the fix, request increases the fast way (Quotas portal, az quota CLI, or as code) while knowing which auto-approve versus route to a human, and use Quota Groups to pool unused quota across subscriptions in a management group so a one-off bump doesn’t become a recurring ticket. This is the focused, vCPU-specific companion to the broader Azure Quotas and Limits: Reading Them, Hitting Them and Requesting Increases — here we go deep on compute cores and the increase machinery, not the whole limit surface.
What problem this solves
A quota is a guardrail Microsoft puts on new allocations so a single subscription can’t seize unbounded capacity in a region and starve everyone else (including you, later). Defaults are deliberately modest — often 10–20 total regional vCPUs on a fresh pay-as-you-go subscription — because Azure can’t pre-commit physical capacity to a subscription that has never used it. Sensible at the fleet level, infuriating at 40 seconds into a deploy, because the error surfaces only when you try to allocate, never before.
What breaks without this knowledge is predictable and expensive. An engineer hits QuotaExceeded, assumes the template is wrong, and burns an hour re-reading Bicep that was always correct. Or they react to SkuNotAvailable with a quota-increase ticket — which can’t help, because that error is offering, not quota — and wait days for a “not applicable” reply. Worst of all, an autoscale rule silently caps at the quota ceiling during a spike: the scale set wants 20 instances, quota allows 12, the extra eight never appear, and no alarm fires because nothing errored on the resource. Capacity you assumed was elastic turns out to have a hard, invisible lid.
Who hits this: everyone who scales compute. It bites hardest on teams promoting a small dev subscription to a larger production one (defaults don’t follow you), on AKS node pools and Scale Sets scaling past the family ceiling under load, on GPU/N-series workloads where defaults are often zero, on Spot fleets exhausting the separate spot ceiling, and on landing-zone teams standing up many subscriptions from the same low defaults. The fix is almost never “make the workload smaller” — it is “see the ceiling before you hit it, request the right one, and pool quota so you stop asking.” The rest of this article enumerates every way that block happens — three vCPU ceilings and two non-quota lookalikes — and the command that confirms each.
Learning objectives
By the end of this article you can:
- Explain the three stacked vCPU ceilings — Total Regional vCPUs, per-family vCPUs, Spot vCPUs — and predict which one a given deployment must clear first.
- Read your current usage against the limit for every vCPU dimension with
az vm list-usageand the unifiedaz quotasurface, and spot the row that is about to bite. - Distinguish a true quota problem (
QuotaExceeded, adjustable) from SKU availability (SkuNotAvailable) and capacity (AllocationFailed) problems no increase can fix. - Request a vCPU increase three ways — Quotas portal,
az quotaCLI, and as IaC/runbook — and predict which auto-approve versus route to a human. - Use Quota Groups to pool and transfer unused vCPU quota across subscriptions in a management group, turning repeated tickets into self-service.
- Run a capacity-planning check before scale-out so
QuotaExceededis a number you verified last week — including the autoscale-capped-silently failure mode. - Map a vCPU SKU to its quota family name (
standardDSv5Family, etc.) reliably, because guessing that name is the usual cause of a request that 400s.
Prerequisites & where this fits
You should already know the compute basics: a VM size (Standard_D4s_v5) belongs to a size family (the Dsv5 series), and the number after the family letter is roughly the vCPU count (a D4s_v5 is 4 vCPUs, a D16s_v5 is 16). You should run az in Cloud Shell, read JSON/table output, and grasp that quotas are scoped per subscription + region (the same subscription has independent ceilings in every region). Knowing what a management group is helps for Quota Groups, and familiarity with Scale Sets and AKS node pools helps because that’s where the ceiling is hit most.
This sits in the Governance & Troubleshooting track as the compute-cores deep cut of the broader Azure Quotas and Limits: Reading Them, Hitting Them and Requesting Increases (read that for the full limit surface, this for vCPU depth). It assumes the VM fundamentals from Your First Azure Virtual Machine: A Step-by-Step Deployment in Portal, CLI and PowerShell and pairs with Decoding Azure VM Series: Picking the Right D, E, F, L, N and M Family for Your Workload, because choosing the family is choosing which quota you spend. Spot quota connects to Azure Spot Virtual Machines Explained: How Eviction, Capacity and Pricing Save You up to 90%, and a request that routes to a human brings in Azure Support Plans Compared: Severity Levels, Response Times and What to Buy.
A quick map of who owns which ceiling during an incident, so you escalate to the right place fast:
| Layer | What it caps | Who usually owns it | Failure class it causes |
|---|---|---|---|
| Per-family vCPU quota | Cores allocatable from one size family in a region | Platform / subscription owner | QuotaExceeded on a specific family |
| Total Regional vCPU quota | Sum of all VM cores in a region | Platform / subscription owner | QuotaExceeded even when the family has room |
| Spot vCPU quota | Cores allocatable as Spot in a region | Platform owner | Spot scale set capped / QuotaExceeded |
| SKU offering | Whether a size exists in region/zone | Microsoft (region rollout) | SkuNotAvailable (no quota request helps) |
| Physical capacity | Whether hardware is free now | Microsoft (datacentre) | AllocationFailed (transient, retry/relocate) |
| Quota Group (mgmt group) | Shared quota pool across subscriptions | Billing / landing-zone team | Transfer fails if group quota is short |
Core concepts
A few mental models make every later diagnosis obvious.
A quota is an adjustable ceiling on a counted, regional resource — not a bill and not a reservation. A vCPU quota counts how many cores you may have allocated at once from a family in a region. It’s not money (you pay for what you run) and not capacity (it doesn’t pre-book hardware); raising it costs nothing and just lifts the lid. The distinction that wastes the most hours is quota versus capacity: QuotaExceeded = your approved ceiling is too low (file a request); AllocationFailed / SkuNotAvailable = Azure can’t or won’t place that size there right now (a quota increase does nothing).
vCPU limits stack in three independent layers, and you must clear all that apply. Every VM consumes its family’s per-family quota, AND the region’s Total Regional vCPUs quota, AND — if Spot — the region’s Spot vCPUs quota. These are separate counters: a four-core D4s_v5 adds 4 to standardDSv5Family and 4 to the Total Regional counter at once. You can have ample family headroom and still be blocked by the regional total, which is why reading all three numbers — not just the one in the error — prevents the next surprise.
The error names the family by its internal quota name, not its friendly name. Azure identifies families by strings like standardDSv5Family and the regional total as cores (Total Regional vCPUs in the portal) — not the marketing names (“Dsv5-series”). Guessing the internal name is the number-one cause of a 400 Bad Request, so read it first from az vm list-usage or az vm list-skus and copy it exactly.
Two more facts shape everything downstream, both developed in their own sections below. Quota is per-subscription and per-region, and defaults don’t travel — dev’s generous eastus tells you nothing about prod’s centralindia, which is the single most common reason “it worked in dev” fails in prod (and the problem Quota Groups solve by pooling across a management group). And increase requests are partly automated — modest bumps on common families auto-approve in seconds, while large jumps, GPU SKUs and capacity-pressured regions route to a support engineer for hours to days.
The vocabulary in one table
Every moving part in one place; the glossary repeats these for lookup.
| Concept | One-line definition | Where it lives | Why it matters |
|---|---|---|---|
| vCPU / core quota | Max cores allocatable at once from a scope | Per subscription + region | The ceiling you hit at scale-out |
| Total Regional vCPUs | Sum-of-all-families cap for a region | Per subscription + region | Blocks even when a family has room |
| Per-family vCPUs | Cap for one size family (standardDSv5Family) |
Per subscription + region | The error you see most often |
| Spot vCPUs | Separate cap for evictable (Spot) cores | Per subscription + region | Spot fleet limited independently |
| Quota family name | Internal id like standardDSv5Family |
Quota API / az output |
Wrong name → request 400s |
| Usage | Cores currently allocated against a limit | Read via az vm list-usage |
The “current usage” in the error |
| Quota increase request | An ask to raise a limit | Quotas portal / az quota |
Auto-approves or routes to support |
| Quota Group | Shared quota pool across subscriptions | Under a management group | Pool/transfer to stop re-asking |
| SKU availability | Whether a size is offered here/in a zone | az vm list-skus |
SkuNotAvailable ≠ quota problem |
| Allocation / capacity | Whether hardware is free right now | Datacentre, runtime | AllocationFailed ≠ quota problem |
Microsoft.Quota |
The unified quota resource provider | ARM control plane | Backs az quota across providers |
The three vCPU ceilings, layer by layer
The single biggest source of confusion is treating “vCPU quota” as one number. It is three, and a deployment fails against the first it exceeds. The stack at a glance, including the two non-quota lookalikes that masquerade as quota errors:
| Ceiling | Internal name (example) | Counts | Typical default (new PAYG) | Adjustable? | Error when hit |
|---|---|---|---|---|---|
| Total Regional vCPUs | cores (a.k.a. Total Regional vCPUs) |
Every VM core in the region, all families | ~10–20 | Yes | QuotaExceeded (regional) |
| Per-family vCPUs | standardDSv5Family, standardFSv2Family, … |
Cores from that one family in the region | Low per family; 0 for some GPU | Yes | QuotaExceeded (family) |
| Spot vCPUs | lowPriorityCores / spot family rows |
Evictable (Spot) cores in the region | Low / 0 | Yes | QuotaExceeded (spot) |
| SKU availability (lookalike) | n/a | Whether the size is offered here/zone | n/a | No — not a quota | SkuNotAvailable |
| Capacity (lookalike) | n/a | Whether hardware is free right now | n/a | No — not a quota | AllocationFailed |
Ceiling 1 — Total Regional vCPUs
This is the region-wide lid: the sum of every VM core running in that region across all families — your D-series web tier, E-series database tier and F-series workers all add into one counter. A fresh pay-as-you-go subscription often starts around 10–20 here, so a few medium VMs plus an AKS cluster hit it early.
Confirm it. Read the Total Regional vCPUs row:
# Total Regional vCPUs usage vs limit for one region
az vm list-usage --location centralindia \
--query "[?contains(localName,'Total Regional vCPUs')].{name:localName, used:currentValue, limit:limit}" \
-o table
If used is at or near limit, the regional total is your blocker regardless of family — the tell-tale is an error whose family line shows headroom yet the deploy still fails, because the regional total (a different counter) is full.
Fix it. Request a higher Total Regional limit, or move footprint to another region so the sum drops. Raising the regional total does not raise any per-family ceiling — they’re independent, so a large regional total with a small family quota still blocks that family.
Ceiling 2 — Per-family vCPUs
The one you see in error messages most. Each VM size family has its own regional ceiling, named with an internal string (standardDSv5Family, …; mapped below). A Standard_D4s_v5 consumes 4 cores from standardDSv5Family; a Standard_D16s_v5 consumes 16. The default is low, and for many N-series GPU sizes it’s literally 0 — you cannot allocate even one until you request quota.
Confirm it. First find which family your SKU maps to (don’t guess):
# Map a VM size to its quota family name and core count
az vm list-skus --location centralindia --size Standard_D4s_v5 \
--query "[0].{size:name, family:family, vCPUs:capabilities[?name=='vCPUs'].value | [0]}" -o json
# -> "family": "standardDSv5Family"
Then read that family’s usage vs limit:
# Per-family usage vs limit (substitute the family from the step above)
az vm list-usage --location centralindia \
--query "[?name.value=='standardDSv5Family'].{family:localName, used:currentValue, limit:limit}" \
-o table
The error itself states the family, current limit, usage and additional required — e.g. “exceeding approved standardDSv5Family Cores quota. Current Limit: 24, Current Usage: 20, Additional Required: 8” — so it already names the family and how many more cores you need.
Fix it. Request a higher per-family ceiling (cleanest), or switch to a family that has headroom — the fastest mitigation in an incident: if Dsv5 is capped but Dsv4/Edsv5 fits, retargeting the SKU clears the block immediately without approval, at the cost of a slightly different price/performance point.
Because the internal name is what you pass to a request — and the wrong one is the usual 400 — keep this size-to-family map handy (always confirm with az vm list-skus --size <size> --query "[0].family"):
| Common size (example) | Series | Internal quota family name | Typical use |
|---|---|---|---|
Standard_D4s_v5 |
Dsv5 | standardDSv5Family |
General-purpose web/app tier |
Standard_E8ds_v5 |
Edsv5 | standardEDSv5Family |
Memory-optimised (DB, cache) |
Standard_F8s_v2 |
Fsv2 | standardFSv2Family |
Compute-optimised (batch, CI) |
Standard_B2s |
Bsv… | standardBSFamily |
Burstable dev/test |
Standard_L8s_v3 |
Lsv3 | standardLSv3Family |
Storage-optimised (high IOPS) |
Standard_NC24ads_A100_v4 |
NC A100 v4 | standardNCADSA100v4Family |
GPU compute (often defaults to 0) |
| any regular VM | — | cores (Total Regional vCPUs) |
The region-wide sum across families |
Ceiling 3 — Spot vCPUs
Spot VMs (evictable, deeply discounted capacity) draw from a separate vCPU ceiling — Spot cores don’t consume your standard quota and aren’t constrained by it; they’re gated by the Spot ceiling, which often starts low or at zero. This catches teams who raised their regular quota generously and then watched a Spot scale set refuse to grow — because the Spot counter, not the regular one, was full.
Confirm it. The spot rows appear in the same usage list, named for low-priority/spot cores:
# Spot / low-priority vCPU usage vs limit
az vm list-usage --location centralindia \
--query "[?contains(localName,'Spot') || contains(localName,'Low')].{name:localName, used:currentValue, limit:limit}" \
-o table
Fix it. Request a higher Spot vCPU quota the same way (just a different quota name). Remember Spot is also subject to eviction and capacity independently of quota — even with ample quota, Azure can evict or refuse instances when it needs the hardware back.
How the three interact — who blocks first
A deployment is checked against every applicable ceiling and fails against the first it would exceed — reasoning about that order prevents the “I raised the quota and it still failed” loop.
| Scenario | Family quota | Regional total | Spot quota | What happens |
|---|---|---|---|---|
| Regular VM, family full | Exceeded | Has room | n/a | Fails: family QuotaExceeded |
| Regular VM, region total full | Has room | Exceeded | n/a | Fails: regional QuotaExceeded (raise the total) |
| Regular VM, both have room | Has room | Has room | n/a | Succeeds (subject to SKU/capacity) |
| Spot VM, spot full, regular fine | Has room | Has room | Exceeded | Fails: spot QuotaExceeded |
| GPU SKU not offered here, quotas fine | Has room | Has room | n/a | Fails: SkuNotAvailable (wrong region/zone) |
| Constrained size, all quotas fine | Has room | Has room | n/a | May fail: AllocationFailed (capacity) |
The discipline that falls out: read all three numbers and verify the SKU is offered before scale-out, so you fix the ceiling that actually blocks you.
Reading usage before it bites
You never want to discover a ceiling from a failed deploy. Two surfaces give you the numbers ahead of time — the compute-specific az vm list-usage / az network list-usages, and the unified az quota (read and write across providers via Microsoft.Quota).
The compute-specific usage commands
az vm list-usage is the fastest read for vCPU ceilings — every compute row for a region with currentValue (used) and limit:
# Every compute quota row for a region, sorted to surface the tightest first
az vm list-usage --location centralindia -o table
# Just the rows that are >80% consumed — your early-warning list
az vm list-usage --location centralindia \
--query "[?limit > \`0\` && currentValue >= (limit * \`0.8\`)].{name:localName, used:currentValue, limit:limit}" \
-o table
For network ceilings (public IPs, NICs), the sibling is az network list-usages --location <region>.
The unified az quota surface
The newer az quota group reads and writes quotas across providers via Microsoft.Quota. For compute, build the scope from subscription and location, then list, show and check usage:
SUB=$(az account show --query id -o tsv)
SCOPE="/subscriptions/$SUB/providers/Microsoft.Compute/locations/centralindia"
# All compute quotas (limits) at that scope
az quota list --scope "$SCOPE" -o table
# Current usage at that scope
az quota usage list --scope "$SCOPE" -o table
# One specific quota — the regional total is named 'cores'
az quota show --resource-name cores --scope "$SCOPE" -o json
| Command | Reads | Writes | Best for |
|---|---|---|---|
az vm list-usage |
Compute usage + limit per region | No | Fast vCPU read, early-warning scan |
az network list-usages |
Network usage + limit per region | No | Public IPs, NICs alongside a VM deploy |
az quota list / usage list / show |
Any provider via Microsoft.Quota |
— | Cross-provider reads, scripting |
az quota create / update |
— | Yes (submits a request) | Programmatic increase requests |
az quota request status list / show |
Request state | No | Tracking whether a bump approved |
The naming rule that saves a 400: the regional total’s --resource-name is cores and a family’s is its internal string — read the exact value from az quota list --scope "$SCOPE" before passing it to create/update.
Reading pays off on a cadence — wire these so a ceiling is verified, not discovered:
| When | Check | Action if tight |
|---|---|---|
| Before any scale-out / new SKU | az vm list-usage for the target family + Total Regional |
Raise the binding ceiling first |
| Daily (scheduled) | Usage ≥ 80% of limit for key families/regions | Alert/page; request ahead of need |
| New subscription or region | Compare defaults to your known footprint | Bootstrap quota; mirror prod into DR |
| Before a failover test | DR-region family + regional limits | Match them to production |
| Onboarding a GPU workload | N-family limit (often 0) |
Request early — routes to support |
Requesting a vCPU increase
Once you know which ceiling blocks you and by how much, request the increase. Three paths, by whether you’re firefighting once or codifying a baseline.
| Path | Best for | Auto-approve likely? | Audit trail |
|---|---|---|---|
| A — Quotas portal | One-off, interactive, “just unblock me now” | Yes for modest common-family bumps | Activity log |
B — az quota CLI |
Scripts, runbooks, repeatable bumps | Same engine as portal | Command + request ID |
| C — IaC / pipeline | Codifying baseline quotas for new subscriptions | Same engine | Source control + pipeline log |
Path A — the Quotas portal
The Quotas experience (portal.azure.com → Quotas → Compute) lists each region’s usage as a bar and offers an Increase action on every adjustable row. Type the new absolute limit (not the delta — have 24, need 28, enter 28); for a modest common-family bump it frequently flips to Approved within seconds, otherwise it routes to support with a trackable request. The right path mid-incident.
Path B — the az quota CLI
For automation or speed, az quota creates or updates a request at the provider+region scope, setting the new absolute limit:
SUB=$(az account show --query id -o tsv)
SCOPE="/subscriptions/$SUB/providers/Microsoft.Compute/locations/centralindia"
# Raise the per-family ceiling to a new absolute value (e.g. 28 cores)
az quota create \
--resource-name standardDSv5Family \
--scope "$SCOPE" \
--limit-object value=28 \
--resource-type dedicated
# If a quota object already exists for that resource, use update instead
az quota update \
--resource-name standardDSv5Family \
--scope "$SCOPE" \
--limit-object value=28
# Track it
az quota request status list --scope "$SCOPE" -o table
az quota request status show --name <requestId> --scope "$SCOPE" -o json
To raise the regional total instead, use --resource-name cores. The exact inputs and the trap for each:
| Input | What to pass | Common mistake |
|---|---|---|
--resource-name |
Internal name: standardDSv5Family (family) or cores (regional total) |
Friendly name (“Dsv5”) or a typo → 400 |
--scope |
/subscriptions/<sub>/providers/Microsoft.Compute/locations/<region> |
Wrong subscription or region in the path |
--limit-object value= |
The new absolute limit (have 24, need 28 → 28) |
Passing the delta (4) instead of the target |
--resource-type |
dedicated (regular) — Spot rows use their own name |
Mixing Spot and regular in one request |
| Region | The region you actually deploy to | Raising the right family in the wrong region |
Path C — codify it as a pipeline/IaC step
Quota requests are an imperative ask against Microsoft.Quota, not a declarable Bicep resource. The clean landing-zone pattern wraps the az quota call in a Bicep deploymentScript so the request lives in source control and runs at subscription bootstrap with a full audit trail:
param location string
param targetFamily string = 'standardDSv5Family'
param newLimit int = 28
resource raiseQuota 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
name: 'raise-${targetFamily}-${location}'
location: location
kind: 'AzureCLI'
properties: {
azCliVersion: '2.61.0'
retentionInterval: 'PT1H'
scriptContent: '''
SCOPE="/subscriptions/${SUB}/providers/Microsoft.Compute/locations/${LOC}"
az quota create --resource-name "$FAM" --scope "$SCOPE" \
--limit-object value=$LIMIT --resource-type dedicated
'''
environmentVariables: [
{ name: 'SUB', value: subscription().subscriptionId }
{ name: 'LOC', value: location }
{ name: 'FAM', value: targetFamily }
{ name: 'LIMIT', value: string(newLimit) }
]
}
}
The script is the unit of change — versioned and reviewed. For a cleaner multi-subscription baseline, Quota Groups (next) let you allocate from a shared pool instead of filing the same request per subscription.
Who auto-approves and who waits
Predicting the path lets you plan the window:
| Request shape | Likely route | Typical time | Why |
|---|---|---|---|
| Modest bump, common family, healthy region | Auto-approved | Seconds | System has headroom and confidence |
| Large jump on a common family | Support review | Hours | Bigger commitment, sanity-checked |
| Any N-series / GPU family from 0 | Support review | Hours–days | Specialised, capacity-constrained |
| Region under capacity pressure | Support review (may decline) | Hours–days | Azure may have no room to grant |
| Spot vCPU bump | Often auto / quick | Seconds–hours | Evictable, less commitment |
| Total Regional vCPUs raise | Usually auto for modest | Seconds | Same engine as family |
If a request routes to support and you’re blocked, the severity and response time you get depends on your support plan — see Azure Support Plans Compared: Severity Levels, Response Times and What to Buy. Quota requests through the Quotas experience do not require a paid support plan, but escalating a stuck one does.
Quota Groups — pooling quota across subscriptions
The painful pattern in any multi-subscription estate: each subscription starts from the same low defaults, so you file the same per-family ticket over and over, and quota stranded in one subscription can’t help another that’s short. Quota Groups fix this. A Quota Group is a quota pool on a management group — think shared wallet. The platform team obtains quota at the group level once; then any member subscription allocates from the pool into itself for a region/family and deallocates (returns) what it isn’t using so a sibling can take it — turning “10 subscriptions × 1 ticket each” into “1 group grant + self-service.”
| Operation | What it does | When you use it | Net effect |
|---|---|---|---|
| Create group quota | Establish/raise the shared pool for a family+region | Standing up the management group’s capacity | One ticket feeds many subs |
| Allocate to subscription | Move quota from the pool into a member sub | A sub needs more cores now | Sub’s limit rises, no per-sub ticket |
| Deallocate from subscription | Return unused quota to the pool | A sub scaled down / project ended | Frees quota for a sibling sub |
| Transfer between subscriptions | Shift quota from sub A to sub B via the pool | Rebalancing without new grants | Stranded quota becomes usable |
Key constraints: Quota Groups operate within one management group whose subscriptions are members; allocations are still per region and per family; and the initial group quota goes through the same request engine — they change distribution, not whether Azure has capacity to grant. The win is operational: after the one-time grant, members self-serve without a support loop. Quota Groups assume the management-group hierarchy exists and are the capacity-distribution layer on top.
Architecture at a glance
No diagram to study here — just one mental model that locates every error in the playbook. Picture a deployment request travelling down a stack of gates, each a counter it must fit under, and the first gate it overflows is the one that rejects it.
An allocation enters carrying a size and count that resolve to a vCPU demand and a family. Gate 1 is the per-family vCPU quota (usage + demand > family limit → family QuotaExceeded). Gate 2 is the Total Regional vCPUs quota, which the same demand is added to — a larger-scope counter that can reject a request the family gate just passed. Spot requests face a parallel Spot vCPU gate. Below the quota gates sit two checks no increase can move: SKU availability (offered in this region/zone? → SkuNotAvailable) and physical capacity (free hardware now? → AllocationFailed). Above everything, the Quota Group feeds the per-subscription limits, so a gate’s “limit” can be topped up from the shared pool without a ticket.
So the diagnostic question is always which gate did I overflow? — a quota gate (raise it or pick another family) or a non-quota gate below it (availability → change region/zone; capacity → retry or relocate). Reading all three counters and confirming availability before scale-out is just walking this gate-stack on paper before the deployment walks it for real.
Real-world scenario
Lumio Retail, a mid-size e-commerce company, runs its catalogue and checkout APIs on an AKS cluster in centralindia, with a Standard_D4s_v5 user node pool (4 vCPUs/node) autoscaling between 4 and 12 nodes. It had run cleanly for months — then came their first big festival sale.
At 19:40 on sale day, traffic spiked and the cluster autoscaler asked to grow the pool from 9 to its max of 12. Three nodes never appeared. No error on the cluster, no failed deployment, no alert — the autoscaler simply logged that it couldn’t scale, and checkout latency climbed as the existing nodes saturated. The on-call engineer assumed an AKS problem and spent twenty minutes in the cluster’s events before someone ran the one command that mattered:
az vm list-usage --location centralindia \
--query "[?name.value=='standardDSv5Family'].{family:localName, used:currentValue, limit:limit}" -o table
# family: Standard DSv5 Family vCPUs | used: 48 | limit: 48
The standardDSv5Family quota in centralindia was 48 cores — exactly 12 nodes × 4 vCPUs. The system and user pools together had consumed all 48, so nodes 10–12 (the ones the sale needed) had nowhere to allocate. A default set long ago and never revisited had silently become the capacity ceiling; nothing “failed” in the way an alert watches for — the allocation just didn’t happen.
The fix was a quota bump: they raised standardDSv5Family from 48 to 96 via the Quotas portal, and because it was a modest increase on a common family in a healthy region it auto-approved in under a minute. The autoscaler kept retrying, picked up the headroom, and the three nodes joined within a couple of minutes — checkout recovered before the sale peaked.
The post-incident review surfaced three lessons. First, autoscale silently caps at the quota ceiling — invisible to “something errored” alerting — so they added a scheduled check that pages when usage crosses 80% of limit for key families. Second, the quota had to be raised in every region they run in: their DR region had the same 48-core default and would have failed an actual failover. Third, they moved the AKS subscriptions under a management group with a Quota Group, granted the family pool once at the group level, and let each subscription allocate from it — so the next environment inherited capacity instead of a ticket. The whole incident was a number someone could have read the week before.
Advantages and disadvantages
Quotas are a guardrail with real upside and real friction:
| Advantages | Disadvantages |
|---|---|
| Prevents a runaway script/subscription from seizing a region’s capacity | Blocks legitimate scale-out at the worst moment (peak load) |
| Forces deliberate capacity planning per region | Defaults are low and don’t follow you to new subs/regions |
| Increase requests are free and often auto-approve in seconds | Larger / GPU / constrained asks route to support and wait |
| Three-layer model lets Azure fairly share scarce families | Three layers are easy to confuse → wrong fix, wasted time |
| Quota Groups let an estate pool and rebalance capacity | Quota Groups need a management group and add a concept to learn |
Reading usage is a one-line az command |
Autoscale capping at quota is silent — no error to alert on |
| A quota grant costs nothing until you actually run the VMs | A grant is not a capacity reservation — hardware can still be unavailable |
When the upside dominates: in any shared or production estate, the guardrail is worth it — you want a deliberate ceiling, and reading usage before scale-out turns the worst-moment block into a non-event. The friction bites hardest on GPU workloads from a zero default and multi-subscription estates re-filing the same ticket — exactly where requesting ahead of need and adopting Quota Groups pays off.
Hands-on lab
Read your real vCPU ceilings, watch an allocation consume quota, and (optionally) request a small increase — all free; we delete the one tiny VM at the end. Run in Cloud Shell (Bash).
Step 1 — Read your Total Regional vCPUs.
LOC=centralindia
az vm list-usage --location $LOC \
--query "[?contains(localName,'Total Regional vCPUs')].{name:localName, used:currentValue, limit:limit}" \
-o table
Expected: one row with your regional total used vs limit.
Step 2 — List your tightest quotas (early-warning scan).
az vm list-usage --location $LOC \
--query "[?limit > \`0\` && currentValue >= (limit * \`0.5\`)].{name:localName, used:currentValue, limit:limit}" \
-o table
Expected: every quota you’ve used at least half of (empty on a quiet subscription is fine).
Step 3 — Map a size to its family and confirm headroom.
az vm list-skus --location $LOC --size Standard_B1s \
--query "[0].{size:name, family:family}" -o json
az vm list-usage --location $LOC \
--query "[?contains(localName,'BS') || name.value=='standardBSFamily'].{family:localName, used:currentValue, limit:limit}" \
-o table
Expected: the size’s family string, then that family’s used/limit — the exact pair of reads you’d do mid-incident to find the blocking ceiling.
Step 4 — Allocate one tiny VM and watch the counter rise.
RG=rg-quota-lab
az group create -n $RG -l $LOC -o table
az vm create -n vm-quota-lab -g $RG --image Ubuntu2204 \
--size Standard_B1s --admin-username azureuser --generate-ssh-keys \
--public-ip-sku Standard --no-wait -o table
Wait ~60 s, then re-read the family from Step 3 — used rose by the VM’s vCPU count (a B1s is 1 vCPU). You just watched usage tick up against the ceiling.
Step 5 — Confirm az quota agrees.
SUB=$(az account show --query id -o tsv)
SCOPE="/subscriptions/$SUB/providers/Microsoft.Compute/locations/$LOC"
az quota usage list --scope "$SCOPE" -o table | head -20
az quota show --resource-name cores --scope "$SCOPE" -o json
Expected: the same numbers via the cross-provider API; the regional total appears as cores.
Step 6 (optional) — Submit a tiny increase request. Only if you want more headroom; this is a real request. Raise the regional total to a new absolute value:
# Read the current limit first, then set new = current + a little
az quota show --resource-name cores --scope "$SCOPE" --query "properties.limit.value" -o tsv
az quota create --resource-name cores --scope "$SCOPE" --limit-object value=<current+4> --resource-type dedicated
az quota request status list --scope "$SCOPE" -o table
Expected: a request that, for a small bump, typically shows Succeeded/Approved quickly.
Validation checklist. You read the vCPU ceilings, mapped a SKU to its family, watched an allocation consume quota, cross-checked via az quota, and (optionally) filed an increase. The steps mapped to what they prove:
| Step | What you did | What it proves |
|---|---|---|
| 1–2 | Read regional total + early-warning scan | You can see ceilings before they bite |
| 3 | Map size → family, read family limit | You find the blocking ceiling, not a guess |
| 4 | Create a VM, watch usage rise | Allocation consumes quota in real time |
| 5 | Cross-check via az quota |
The unified surface agrees; naming is cores |
| 6 | File a small increase | The request path and auto-approval are real |
Cleanup.
az group delete -n $RG --yes --no-wait
Cost note. A B1s is a few paise per hour and the rest is read-only API calls; an hour of this lab is well under ₹20, and deleting the resource group stops everything. Reading quotas and filing increases is always free.
Common mistakes & troubleshooting
This is the playbook — the part you bookmark. First the error-code reference (the exact strings, what each means, and whether a quota increase even applies), then a scannable symptom→cause→confirm→fix table for mid-incident, then full reasoning for the entries that bite hardest. The costliest codes are the non-quota lookalikes — SkuNotAvailable and AllocationFailed — which read like quota problems but no increase fixes.
| Error code / string | What it means on Azure | Quota-fixable? | How to confirm | First fix |
|---|---|---|---|---|
QuotaExceeded (family) |
Per-family vCPU ceiling reached | Yes | az vm list-usage family row at limit; error states Current Limit/Usage |
Raise that family or retarget to one with headroom |
QuotaExceeded (Total Regional vCPUs) |
Region-wide cores ceiling reached | Yes | az vm list-usage → Total Regional vCPUs row at limit |
Raise --resource-name cores, or shed region footprint |
OperationNotAllowed (cores) |
Request would exceed an allowed core count | Yes | Error text names the limit and required cores | Raise the named ceiling; lower count × size |
SkuNotAvailable |
Size not offered in this region/zone | No — offering, not quota | az vm list-skus -l <region> --size <size> --zone <z> empty/restricted |
Change region/zone or size |
AllocationFailed |
No free hardware for size+zone now | No — capacity, not quota | Error is AllocationFailed, quotas show headroom |
Retry, relax zone/size, or Capacity Reservation |
OverconstrainedAllocationRequest |
Too many constraints (zone+size+pinning) can’t be placed | No — capacity | Same as above with multiple constraints | Relax a constraint (zone/size) |
400 Bad Request (on az quota create) |
Wrong/typo’d --resource-name |
n/a (request error) | Compare to az quota list --scope "$SCOPE" |
Pass the exact internal name |
RequestDisallowedByPolicy |
Azure Policy blocked the size/region | No — governance | Activity log shows the policy assignment | Use an allowed size/region or amend policy |
With the codes pinned, the symptom-first playbook:
| # | Symptom | Root cause | Confirm (exact cmd / portal path) | Fix |
|---|---|---|---|---|
| 1 | Deploy dies QuotaExceeded naming a family |
Per-family vCPU ceiling reached | az vm list-usage -l <region> --query "[?name.value=='<family>']" (used≈limit) |
Raise that family, or retarget to one with headroom |
| 2 | Family has room, deploy still QuotaExceeded |
Total Regional vCPUs ceiling reached (different counter) | az vm list-usage → Total Regional vCPUs row |
Raise the regional total (--resource-name cores), or move footprint |
| 3 | Autoscale/AKS won’t grow, no error, no alert | Allocation silently capped at quota ceiling | az vm list-usage family row at limit; AKS event “could not scale” |
Raise the family quota; add an 80%-usage alert |
| 4 | az quota create returns 400 Bad Request |
Wrong --resource-name (friendly name / typo) |
az quota list --scope "$SCOPE" for the exact internal name |
Pass the exact string (standardDSv5Family, cores) |
| 5 | GPU/N-series VM fails with quota 0 | Default per-family quota is 0 for that family | az vm list-usage shows limit 0 for the N-family |
Request the GPU family quota (routes to support; hours–days) |
| 6 | SkuNotAvailable; request “not applicable” |
Size isn’t offered in that region/zone (not quota) | az vm list-skus -l <region> --size <size> --zone <z> (empty) |
Change region/zone or pick an offered size — no increase helps |
| 7 | Quota fine, deploy fails AllocationFailed |
Capacity — no hardware for that size+zone now | Error is AllocationFailed/OverconstrainedAllocationRequest |
Retry, relax zone/size, or use a Capacity Reservation |
| 8 | Spot scale set won’t grow though regular quota is huge | Spot vCPU ceiling is separate and full/zero | az vm list-usage Spot/Low rows |
Raise the Spot quota specifically |
| 9 | “It worked in dev, fails in prod” | New subscription/region inherits low defaults | Compare az vm list-usage between the two |
Raise quota in the prod sub/region; consider Quota Groups |
| 10 | Increase request stuck “pending”/in review | Large/constrained ask routed to a human | az quota request status show --name <id> --scope "$SCOPE" |
Wait/escalate via support; meanwhile retarget family/region |
| 11 | Raised quota, deploy still fails same family | Raised the wrong region, or the regional total not the family (or vice versa) | Re-read the family and Total Regional rows for the exact region deployed | Raise the ceiling that’s actually at limit, in the deploy region |
| 12 | Reservation/scale-set reports quota error at create | Total count × size exceeds family or regional cap | Sum instances × vCPUs vs the two limits | Lower count, split across regions, or raise the binding ceiling first |
| 13 | Quota Group transfer/allocation fails | Group pool short, or sub not in the management group | Check MG membership and group quota balance | Top up the pool; fix membership; allocate per region+family |
| 14 | Portal shows quota OK but CLI deploy fails | Wrong region or subscription context | az account show; confirm --location matches the deploy |
Align subscription (az account set) and region |
The entries whose table row alone doesn’t capture why:
The family has room, but the deploy still returns QuotaExceeded (row 2). You hit the Total Regional vCPUs ceiling — a separate, region-wide counter summing all families. Confirm with az vm list-usage -l <region> where the Total Regional vCPUs row is at limit even though the family row isn’t. Fix by raising the regional total (az quota create --resource-name cores ...), not the family — raising the family does nothing here — or shed footprint to another region.
Autoscale or AKS won’t add nodes, with no error and no alert (row 3). The autoscaler asked for capacity exceeding a vCPU ceiling, so the allocation silently didn’t happen — it’s not an error on the resource. Confirm with az vm list-usage showing the family or regional row at its limit while the instance count stays flat under load. Fix by raising the binding quota and, critically, adding an alert comparing currentValue to limit at ~80% so it never again hides behind silence. This is the costliest failure mode because nothing pages you.
The two non-quota lookalikes — SkuNotAvailable and AllocationFailed (rows 6–7). These read like quota errors but no increase fixes either, which is why they waste the most time. SkuNotAvailable means the size isn’t offered in that region/zone (an availability fact — confirm with az vm list-skus ... --zone <z> returning empty; fix by choosing an offered region/zone/size). AllocationFailed / OverconstrainedAllocationRequest means physical capacity — no free hardware for that size+zone right now; quota is your permission, capacity is the hardware. Fix by retrying, relaxing the zone/size constraint, or guaranteeing placement with a Capacity Reservation.
Best practices
- Read all three ceilings before you scale out. Total Regional, per-family, and (if Spot) the Spot quota — the deploy fails against the first it overflows, so check them all, not just the family in the last error.
- Map the SKU to its family name from
az, never from memory.az vm list-skus --size <size> --query "[0].family"gives the exact string; using it verbatim avoids the400. - Alert on usage-vs-limit at ~80%, per key family and region. Autoscale capping at quota is silent — a scheduled check that pages at 80% is the single most valuable safeguard against the invisible failure.
- Request ahead of need, in every region including DR. N-series defaults are often 0 and route to support; a failover region with default quota is a failover that fails. Mirror production quotas into the recovery region, the week before, not at 2 a.m.
- Use Quota Groups for multi-subscription estates. Grant the pool once at the management-group level, then let subscriptions allocate and rebalance — N tickets become self-service.
- Codify baseline quotas in subscription bootstrap. Run the
az quotacalls from a config-driven pipeline step so new subscriptions start with sane ceilings, not raw defaults. - Treat a granted quota as permission, not a reservation. For guaranteed placement of a constrained size, pair the quota with a Capacity Reservation — quota alone doesn’t hold hardware.
- Mid-incident, prefer retargeting a family over waiting on a big request. If
Dsv5is capped butEdsv5/Dsv4fits, switching the SKU unblocks instantly while the increase processes.
Security notes
Quotas are a capacity guardrail, but the operations around them have a security surface worth locking down:
- Quota management is privileged. Increase requests and (especially) Quota Group allocations change how much capacity a subscription can seize. Grant it through least-privilege RBAC — the Quota Request Operator role for those who file requests — not Contributor/Owner. See the patterns in Azure RBAC: Custom Roles, Least Privilege, Actions and NotActions.
- Quotas are a blast-radius control, not just a nuisance. A bounded vCPU ceiling caps how much a compromised credential or runaway pipeline can spin up in a region — both cost and sprawl. Don’t reflexively raise every quota to the maximum “to be safe”; an over-wide ceiling is a wider blast radius.
- Govern Quota Group membership. Since a Quota Group lets members draw shared capacity, control which subscriptions join the backing management group and who can allocate — an unexpected member can drain quota a sibling needed.
- Audit quota changes. Requests and allocations land in the Activity Log; review them and consider an alert on quota-write operations so a surprise jump is visible.
- Don’t leak topology in scripts. Capacity-planning scripts that enumerate every subscription’s quota reveal your fleet’s shape; treat their output as sensitive and run them with a scoped identity.
Cost & sizing
The most important cost fact is the one people misunderstand: a quota costs nothing. Raising a vCPU limit adds nothing to your bill — you pay only for VMs you run, so there’s no cost reason to keep quotas low (only the blast-radius reasons above). What drives cost is what you run under the ceiling:
- Cores running, not cores permitted. Your bill tracks allocated vCPUs (size × count × hours). A 96-core quota with 12 cores running costs the same as a 12-core quota with 12 running. Size the quota for headroom; size the deployment for the bill.
- Autoscale + quota = your real ceiling. A max of 20 nodes behind a 48-core quota (12 nodes) silently costs less and serves worse than expected. Reconcile the two so budgeted cost equals the capacity you get.
- Spot for elastic, quota-separate savings. Spot vCPUs are up to ~90% cheaper and draw from their own quota — for fault-tolerant burst they cut cost dramatically without touching regular quota, at the price of eviction.
- Capacity Reservations cost money; quotas don’t. A reservation charges for the reserved capacity whether or not you use it — the opposite of a free quota. Reach for it only when placement certainty is worth the standing cost.
- Right-size the family to right-size both quota and bill. A memory-optimised
Esize where aDsuffices burns more cores per workload — quota and money. Family choice is a cost lever, covered in Decoding Azure VM Series.
A rough picture for a small production AKS footprint: a Standard_D4s_v5 pool autoscaling 4–12 nodes uses 16–48 vCPUs and runs roughly ₹70,000–₹2,10,000/month depending on time at peak (pay-as-you-go Linux, indicative — price your exact region/SKU). The quota to support it (≥48 family cores plus regional headroom) is free; only the running nodes cost. Move the burst to Spot and peak cost can halve, gated by the separate, also-free Spot quota.
Interview & exam questions
1. What are the three vCPU ceilings a VM deployment must clear, and how do they relate? Per-family vCPUs (cores from one size family in a region), Total Regional vCPUs (sum of all families), and — for Spot VMs — Spot vCPUs (a separate evictable ceiling). A regular VM must fit under both the family and the regional total; a Spot VM under the spot ceiling too. The deploy fails against whichever it overflows first, so a request can pass the family quota and still fail the regional total.
2. A deployment fails QuotaExceeded on a family, but az vm list-usage shows that family has headroom. What’s happening? It hit the Total Regional vCPUs ceiling, a different counter that sums every family in the region. The family gate passed; the regional gate didn’t. The fix is to raise the regional total (--resource-name cores) or shed footprint to another region — raising the family quota would do nothing.
3. How do you tell a quota problem from a SKU-availability problem from a capacity problem? QuotaExceeded = your approved ceiling is too low (adjustable; file a request). SkuNotAvailable = the size isn’t offered in that region/zone (change region/zone/size; a quota request can’t help). AllocationFailed = no free hardware for that size+zone right now (retry, relocate, or use a Capacity Reservation). Only the first is solved by an increase.
4. Why does “it worked in dev, fails in prod” happen with quotas? Quotas are per-subscription and per-region, and defaults don’t travel. The production subscription (or a new region) starts from Azure’s low defaults that the dev subscription outgrew long ago. You must raise quota in the actual sub/region you deploy to; Quota Groups can let an estate inherit pooled capacity instead.
5. An AKS cluster won’t add nodes during a spike, with no error and no alert. What is the likely cause and the safeguard? The cluster autoscaler asked for capacity exceeding a vCPU quota, so the allocation silently didn’t happen — it’s not an error on the resource. Confirm with az vm list-usage showing the family/regional row pinned at its limit. The safeguard is an alert comparing currentValue to limit at ~80%, because this failure is invisible to ordinary error alerting.
6. What is a Quota Group and what problem does it solve? A Quota Group is a shared quota pool associated with a management group; member subscriptions allocate quota from the pool into themselves and return (deallocate) unused quota for siblings to use. It replaces filing the same per-family increase ticket across many subscriptions with a one-time group grant plus self-service allocation, and lets stranded quota in one subscription be rebalanced to another.
7. You run az quota create for a vCPU bump and get 400 Bad Request. Most likely cause? The --resource-name is wrong — you passed the friendly name or a typo instead of the internal string. Use the exact value from az quota list --scope "$SCOPE": standardDSv5Family for a family, cores for the Total Regional vCPUs. Guessing the name is the usual cause of the 400.
8. Which vCPU increase requests auto-approve and which route to a human? Modest bumps on common families in healthy regions typically auto-approve in seconds. Large jumps, specialised/GPU families (often defaulting to 0), and capacity-pressured regions route to a support engineer and take hours to days. Spot and Total-Regional bumps for modest amounts usually auto-approve. Knowing the path lets you plan the deploy window.
9. Does raising a quota guarantee you can deploy that many cores? Does it cost anything? No to both as people assume: a quota is permission, not a hardware reservation — you can still hit AllocationFailed if capacity is short — and raising it is free (you pay only for VMs you run). For guaranteed placement of a constrained size you need a Capacity Reservation, which charges whether or not you use it.
10. A Spot scale set won’t grow even though your regular quota is large. Why? Spot VMs draw from a separate Spot vCPU ceiling, not your regular regional/family quotas, and the Spot one is often low or zero. Raise the Spot quota specifically. Note that even with ample Spot quota, instances can be evicted or refused on capacity grounds independent of quota.
11. How would you proactively prevent quota surprises across a 20-subscription estate? Codify baseline quotas in subscription bootstrap (config-driven az quota calls), mirror production quotas into DR regions, alert on usage at ~80% per key family/region, and adopt Quota Groups so subscriptions allocate from a shared pool rather than each filing tickets — making QuotaExceeded a number you verified last week, not a 2 a.m. discovery.
12. Where does az quota get its cross-provider ability, and what’s the scope you pass for compute? It works through the unified Microsoft.Quota resource provider, which fronts per-provider quotas. For compute you pass a provider+region scope: /subscriptions/<sub>/providers/Microsoft.Compute/locations/<region>, then list/show/create against resource names like cores or a family string.
These map to AZ-104 (Administrator) — manage subscriptions, governance and compute — and AZ-305 (Solutions Architect) — design for capacity and scale, where vCPU limits and Quota Groups inform subscription/region topology. A compact cert-mapping for revision:
| Question theme | Primary cert | Objective area |
|---|---|---|
| Three vCPU ceilings; reading usage | AZ-104 | Manage subscriptions, governance, compute |
Increase requests; az quota |
AZ-104 | Configure resource policies; CLI |
| Quota Groups; multi-sub capacity | AZ-305 | Design governance & scale |
| Quota vs capacity vs availability | AZ-305 / AZ-104 | Design/operate compute reliably |
| Autoscale capped at quota | AZ-104 | Configure and monitor scale |
Quick check
- A deployment fails
QuotaExceedednamingstandardDSv5Family, butaz vm list-usageshows that family at 40/96 cores. What other ceiling do you check, and what command? - True or false: requesting and being granted a vCPU quota increase guarantees you can deploy that many cores immediately.
- Your
az quota createfor a family bump returns400 Bad Request. Name the single most likely cause and how to get the right value. - An autoscaling AKS pool stops adding nodes at peak with no error in the cluster and no alert. What is the most likely cause, and the one safeguard that would have caught it?
- You raised the
standardDSv5Familyquota ineastusbut the prod deploy incentralindiastill fails the same way. Why?
Answers
- Check the Total Regional vCPUs ceiling — a separate region-wide counter — with
az vm list-usage -l <region> --query "[?contains(localName,'Total Regional vCPUs')]". The family gate passed; the regional total is likely the blocker, and you’d raise--resource-name cores, not the family. - False. A quota is permission, not a hardware reservation. You can still hit
AllocationFailedif Azure lacks free capacity for that size/zone. For guaranteed placement you need a Capacity Reservation. - The
--resource-nameis wrong — likely the friendly name or a typo instead of the internal string. Read the exact value fromaz quota list --scope "$SCOPE"(e.g.standardDSv5Family,cores) and pass it verbatim. - The autoscaler asked for capacity exceeding a vCPU quota, so the allocation silently didn’t happen — it’s not an error on the resource. Confirm with
az vm list-usageshowing the family/regional row at its limit. The safeguard is an alert comparingcurrentValuetolimitat ~80%, since this failure is invisible to ordinary error alerting. - Quotas are per-region and defaults don’t travel —
eastusandcentralindiahave independent ceilings. You raised the wrong region; raise the family (and regional total) quota incentralindia, the region you actually deploy to.
Glossary
- vCPU / core quota — the max cores you may have allocated at once from a scope (family or regional total) in a subscription + region. Adjustable; free to raise.
- Total Regional vCPUs — the region-wide ceiling summing cores across all families; internal name
cores. Blocks a deploy even when a family has headroom. - Per-family vCPUs — the ceiling for one VM size family in a region (
standardDSv5Family). The most commonly hit quota; some GPU families default to 0. - Spot vCPUs — a separate ceiling for evictable (Spot) cores, independent of regular quotas; often low or zero by default.
- Quota family name — the internal identifier (
standardDSv5Family,cores) you must use to read or request quota; the friendly series name doesn’t work. - Usage (
currentValue) — cores currently allocated against a limit; the “Current Usage” in aQuotaExceedederror, scanned withaz vm list-usage. - Quota increase request — an ask to raise a limit to a new absolute value via the portal,
az quota, or REST; auto-approves for modest common-family bumps, else routes to support. - Quota Group — a shared quota pool on a management group; member subscriptions allocate from it and return unused quota, enabling estate-wide pooling without per-subscription tickets.
Microsoft.Quota— the unified resource provider backingaz quota, fronting per-provider quotas through one scoped surface.- SKU availability — whether a VM size is offered in a region/zone (
az vm list-skus); aSkuNotAvailablefailure is an offering fact, not a quota, and no increase fixes it. - Allocation / capacity — whether free hardware exists for a size+zone right now; an
AllocationFailedis a capacity event (retry/relocate/reserve), distinct from a quota. - Capacity Reservation — a paid reservation holding hardware for a size/zone so allocation is guaranteed; unlike a quota, it charges whether or not you use it.
- Quota Request Operator — the least-privilege RBAC role to submit quota increase requests without broad Contributor/Owner rights.
Next steps
You can now localise any vCPU allocation failure to the exact ceiling, request increases the fast way, and pool quota across an estate. Build outward:
- Next: Azure Quotas and Limits: Reading Them, Hitting Them and Requesting Increases — the broad limit surface (public IPs, storage accounts, network resources) beyond compute cores.
- Related: Decoding Azure VM Series: Picking the Right D, E, F, L, N and M Family for Your Workload — choosing the family is choosing which quota you spend.
- Related: Azure Spot Virtual Machines Explained: How Eviction, Capacity and Pricing Save You up to 90% — the separate Spot quota and the eviction/capacity trade-off behind it.
- Related: Troubleshooting Azure Deployment Failures: Reading ARM Error Codes and Activity Logs — read the
QuotaExceeded/SkuNotAvailable/AllocationFailedcodes in context with every other deploy error. - Related: Azure RBAC: Custom Roles, Least Privilege, Actions and NotActions — scope who can manage quotas and Quota Group allocations.
- Related: Azure Support Plans Compared: Severity Levels, Response Times and What to Buy — what happens when a quota request routes to a human and you need it fast.