Azure OpenAI Provisioned Throughput Underutilized
What does ZopNight detect here?
Azure OpenAI provisioned (PTU) deployments averaging under 50% utilization across at least 7 days of coverage get a right-sizing recommendation. Targets respect real deployment minimums of 15 PTU for Global and DataZone, 25 for Regional. Savings come from per-PTU-hour rates over 730 hours, never a flat fraction.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1395 |
| Category | rightsizing |
| Severity | medium |
| Metric | none — pure configuration read |
| Source | openai_ptu_underutilized.go |
Where it applies
PTU utilization and the deployment’s own SKU
- AzureOpenAIProvisionedManagedUtilizationV2: Azure Monitor PTU utilization percentage. Emitted only by provisioned (PTU) deployments; its absence is the natural pay-as-you-go gate (never flagged). Fetched at the account level with no per-deployment split, so on an account running more than one PTU deployment the average is blended across all of them (known limitation, needs an aggregator-side per-deployment metric split, not fixed here).
- resource.Type must equal azure-openai.
- ResourceMetric.MaxCoverageDays >= 7 (MinMaxCoverageDays): guards a warm-up dip on freshly deployed PTU.
- child azure-openai-deployment.UnitCount (deployed PTU) + deployment SKU (GlobalProvisionedManaged/DataZoneProvisionedManaged/ProvisionedManaged); Standard/PAYG deployments are skipped (no PTU meter). Matched via child.ParentUID == account.UID OR the discoverer’s synthetic “azure-openai-deployment-parent:<accountUID>” grouping-node UID (see above).
Gates before a PTU right-size is offered
fires when AzureOpenAIProvisionedManagedUtilizationV2.Average < 50.0% AND MaxCoverageDays >= 7 AND the account has ≥1 Provisioned Managed PTU child with a known per-PTU-hour rate AND the right-sized target is below the deployed count.Rebuilding cost from per-PTU-hour rates
currentMonthly = Σ_d (deployedPTU_d × ratePerPTUHour_d × 730) over the account’s PTU child deployments (each priced at its deployment-type rate, so a mix of Global/Regional/DataZone is exact). rightsizedPTU = max(ceil(deployedPTU × util) rounded up to the deployment type’s scale increment, minCommitment); reduciblePTU = deployedPTU − rightsizedPTU. perPTUMonthly = currentMonthly / deployedPTU, savings = perPTUMonthly × reduciblePTU (no fabricated fraction). Per-type min commitment / increment (fixed 2026-07-02): Global and DataZone deployments floor at 15 PTU in increments of 5; the Regional (bare “ProvisionedManaged”) deployment type floors at 25 PTU in increments of 25. Previously a single flat 15-PTU floor was applied to all types, which could recommend a non-deployable Regional target below its true minimum. When an account mixes deployment types, minCommitment/increment are the conservative sum of each matched child’s own type-minimum and the maximum of each child’s own increment. The rule abstains (returns nil) when: no PTU child (count producer absent), no rate for the region (rate producer absent), a PTU child has no deployed-count signal (fail-closed on the whole account to avoid under-counting), util ≥ 50%, thin coverage, or the right-sized target is not below deployed (already minimal). PTU is not an InstanceType-keyed VM SKU, so RealDeltaSavings/DeriveCatalogDiffSavings do not apply; the per-PTU-hour reconstruction is the concrete path.
Reducing the PTU count on the deployment
- Azure AI Foundry portal → your resource → Deployments → select the provisioned deployment
- Review the PTU utilization trend (Monitoring → Metrics → Provisioned-managed Utilization V2)
- Reduce the deployment’s PTU count toward sustained demand (target shown in the rec), or recreate it as a Standard (pay-as-you-go) deployment
- If the PTU capacity is under a 1-month/1-year reservation, right-size at renewal rather than mid-term
- Note: scaling PTU down releases capacity to the regional pool and may not be reclaimable, so confirm headroom first
The provisioned-managed utilization series
AzureOpenAIProvisionedManagedUtilizationV2 (30d lookback)