This page explains how Mavvrik savings recommendations are generated for Microsoft Azure. For each recommendation it shows the logic or criteria used to identify the resource, default thresholds or lookback periods where applicable, the Reason and Action the recommendation presents in-product, and the metrics involved.
The Reason and Action columns show the exact wording each recommendation displays in the product; text in {braces} marks where live values — utilization, sizes, thresholds, resource names — are filled in for the specific resource.
Thresholds and lookback periods are configurable per policy. Recommendations are intended to support review and decision-making — customers should validate workload ownership, business criticality, performance requirements, and retention policies before taking action. Recommendations never change customer cloud resources.
|
Savings Type |
What it means |
|---|---|
|
Idle |
Resources that are provisioned but showing no meaningful activity — no connections, no traffic, or near-zero utilization over the lookback period. Strong candidates for stopping, pausing, archiving, or deleting, since they incur cost without supporting an active workload. |
|
Rightsize |
Resources that are in use but don't match their actual workload demand — oversized and underutilized, or on a pricier tier / plan / license than needed. Candidates for resizing, configuration or tier changes, scheduling, or a more cost-effective commitment or licensing option, rather than being removed outright. |
|
Orphan |
Resources that are no longer attached to or supporting any other active resource — such as unattached disks, unused public IPs, or private endpoints whose target is gone. These typically serve no function on their own and are strong candidates for deletion. |
|
License |
Resources that may be using a more expensive licensing model than necessary, such as pay-as-you-go or license-included pricing, when existing licenses, subscriptions, or hybrid benefits could be applied. Candidates for applying bring-your-own-license benefits, reusing eligible licenses, or switching to a more cost-effective licensing option without changing or removing the workload. |
Azure Idle Recommendations
Azure resources that may be unused, inactive, or no longer required based on utilization, connection activity, age, or attachment status.
|
Recommendation |
Description |
How Recommendation Is Generated |
Reason |
Action |
Metrics |
|---|---|---|---|---|---|
|
Virtual Machine Idle |
Running VMs with near-zero activity should be reviewed for stop-deallocate or deletion rather than resizing. |
Mavvrik evaluates VM usage over a configurable lookback period, with 30 days used by default. A running VM is flagged as idle when the 95th percentile of Max CPU % is within 0%–5% (default), with memory at or below 65% and network near zero. Requires at least 80% telemetry coverage; scale-set VMs are excluded. |
Virtual Machine is idle — CPU p95 {cpu}%, memory p95 {mem}%, network ~0 Mbps over the last {N} days. |
Stop-deallocate the VM, or delete it. Cascade: Delete the managed disk after the parent VM is removed. Release the static public IP, or re-associate it to a running VM. |
CPU % (95th pct, Max) + memory % + network |
|
Virtual Machine Non-Production Parking |
Non-production VMs idle outside business hours should be reviewed for an automatic stop/start schedule. |
Mavvrik evaluates off-hours activity over a configurable lookback period, with 30 days used by default (off-hours = nights and weekends; business hours 07:00–19:00 by default). A pay-as-you-go, dev/test VM is flagged when off-hours CPU stays 0%–10% with low network and connections. Reservation-covered VMs are excluded, since parking them frees no cash. |
Non-production VM is idle outside business hours — CPU p95 {cpu}% during the {start}:00–{end}:00 window over {N} days. |
Apply an Azure Automation / DevTest stop-deallocate + start schedule so the on-demand VM is parked outside business hours. |
Off-hours CPU % + network + connections |
|
Long Stopped Virtual Machines |
VMs stopped (deallocated) with no activity for an extended period keep billing for their OS disk and should be reviewed for deletion. |
Mavvrik evaluates VM power state and activity over a configurable lookback period, with 30 days used by default. A VM is flagged when it has been stopped (deallocated) for the whole window with no CPU telemetry, while its OS disk still bills. |
VM has been stopped (deallocated) with no activity for {N} days; its OS disk ({OS disk}) continues to bill. |
Delete the long-stopped VM to reclaim OS disk cost. |
N/A (VM power state + OS-disk cost) |
|
SQL DTU Database Idle |
Online, billing DTU-model SQL databases with no connections over the window appear abandoned and should be reviewed. |
Mavvrik evaluates database session activity over a configurable lookback period, with 30 days used by default. An Online, billing DTU-tier database (Basic/Standard/Premium) is flagged when it had zero client sessions across the window. System and master databases are excluded. |
SQL database had zero client sessions for all {N} days (peak {sessions} concurrent sessions) - it appears abandoned. |
Delete the abandoned SQL database (after review). |
Peak client sessions |
|
vCore SQL Database Idle |
Online, billing provisioned-vCore SQL databases with no connections over the window appear abandoned and should be reviewed. |
Mavvrik evaluates database session activity over a configurable lookback period, with 30 days used by default. An Online, billing provisioned-vCore database (GeneralPurpose/BusinessCritical/Hyperscale, non-serverless) is flagged when it had zero client sessions across the window. System databases are excluded. |
vCore SQL database had zero client sessions for all {N} days (peak {sessions} concurrent sessions) - it appears abandoned. |
Convert to serverless with auto-pause, or delete if abandoned. |
Peak client sessions |
|
SQL Serverless Database Idle |
Serverless databases that are abandoned (zero sessions, including already-paused) or that sit idle with auto-pause off should be reviewed. |
Mavvrik evaluates serverless activity over a configurable lookback period, with 30 days used by default. A serverless database (status Online or Paused; geo-replicas and secondaries excluded) is flagged in two cases: (A) it had zero client sessions across the window — abandoned, including already-paused databases still incurring storage cost; or (B) auto-pause is disabled and it is idle (average CPU below 5%) for at least 80% of hours with one or fewer concurrent sessions. |
Abandoned: Serverless SQL database had zero client sessions for all {N} days (peak {sessions} concurrent sessions) - it appears abandoned. Idle (auto-pause off): Serverless SQL database has auto-pause disabled (autoPauseDelay = -1) yet is idle {idle}% of hours (avg CPU below {cpu}%) over the last {N} days, with p95 {sessions} concurrent sessions. It bills minimum-vCore compute around the clock. |
Delete the idle SQL database OR Delete the abandoned serverless SQL database (after review); or enable auto-pause on the idle serverless database so idle compute stops billing. |
Peak client sessions + average CPU % (idle-hour share) |
|
Elastic Pool Idle |
Ready, billing elastic pools with no connections over the window appear idle and should be reviewed. |
Mavvrik evaluates pool session activity over a configurable lookback period, with 30 days used by default. A Ready, billing pool is flagged when it had zero client sessions across the window. System pools are excluded; at least 80% coverage is required. |
Elastic pool had zero client sessions for all {N} days (peak {sessions} concurrent sessions) while Ready and billing 24x7 at its provisioned eDTU/vCore — it appears idle. |
Delete the idle elastic pool, or convert its databases to a serverless tier with auto-pause. |
Peak client sessions |
|
MySQL Flexible Server Idle |
MySQL Flexible Servers in the Ready state with no client connections over the window appear abandoned and should be reviewed. |
Mavvrik evaluates connection activity over a configurable lookback period, with 30 days used by default. A Ready-state MySQL Flexible Server is flagged when peak active connections stayed at zero across the window while still billing compute. Requires at least 80% coverage; Reserved-Instance / Savings-Plan-covered servers (which bill 0) are excluded. |
MySQL flexible server had zero client connections for all {N} days (peak {connections} concurrent) - it appears abandoned. |
Stop the server to halt compute billing, or delete it if abandoned. |
Peak active connections |
|
PostgreSQL Flexible Server Idle |
PostgreSQL Flexible Servers in the Ready state with no client connections over the window appear abandoned and should be reviewed. |
Mavvrik evaluates connection activity over a configurable lookback period, with 30 days used by default. A Ready-state PostgreSQL Flexible Server is flagged when peak active connections stayed at zero across the window while still billing compute. Requires at least 80% coverage; Reserved-Instance / Savings-Plan-covered servers (which bill 0) are excluded. |
PostgreSQL flexible server had zero client connections for all {N} days (peak {connections} concurrent) - it appears abandoned. |
Stop the server to halt compute billing, or delete it if abandoned. |
Peak active connections |
|
Disk Idle |
Attached disks doing no read/write work should be reviewed for a cheaper disk type. |
Mavvrik evaluates disk IO over a configurable lookback period, with 30 days used by default. An attached SSD disk is flagged when its 95th-percentile read+write IOPS and throughput are at zero, so it can move to a cheaper disk type (OS disks stay within SSD tiers). |
Managed disk is idle — p95 {IOPS} IOPS / {MBps} MBps over {N} days while attached and billing. |
Downgrade the idle managed disk from {current SKU} to {target SKU} ({target tier}). |
IOPS + throughput (95th pct) |
|
Disk Attached to Stopped VM |
Data disks attached to a stopped (deallocated) VM keep billing at the full rate while doing no work and should be reviewed. |
A configuration / state check (no lookback). A managed data disk is flagged when it is in the Reserved state — attached to a stopped (deallocated) VM — is not shared, and is still billing. OS disks are excluded. |
Managed data disk ({SKU}, {size} GiB) is attached to a stopped (deallocated) VM and still bills while doing no work. |
Review; snapshot, detach from the VM (or delete the decommissioned VM), then delete the data disk |
N/A (disk state + parent VM power state) |
|
Storage Account Idle |
Storage accounts holding essentially no data yet still billing should be reviewed for deletion. |
Mavvrik evaluates account usage over a configurable lookback period, with 30 days used by default. An account is flagged when peak stored data stays under 1 MB, transactions are at or below 10,000, and ingress at or below 10 MB, while still billing. An account that ever held real data is never flagged. |
Storage account "{name}" ({SKU}) is idle — peak used capacity {bytes} bytes and {transactions} transactions over the last {N} days. |
Delete the idle storage account. |
Used capacity + transactions + ingress |
|
Log Analytics Workspace Idle |
Log Analytics workspaces ingesting essentially no data over the billed month yet still provisioned should be reviewed for deletion. |
Mavvrik evaluates log ingestion over the last complete billed month. A workspace is flagged when its ingested volume stays at or below ~0 GB (0.0001 GB by default) while still billing. |
Log Analytics workspace "{name}" (SKU {SKU}, {retention}-day retention, {region}) is a zombie - it ingested ~0 GB over the billed month yet remains provisioned. |
Delete the zombie Log Analytics workspace. |
Ingested log volume (GB, billed month) |
|
App Service Plan Instance Unused |
Dedicated App Service plans hosting zero apps keep billing their reserved workers and should be reviewed. |
A configuration check (no lookback). Mavvrik flags a dedicated-tier App Service plan hosting zero apps that still incurs a charge. Serverless / Consumption and Free / Shared plans are excluded. |
App Service plan ({tier} {SKU}, {region}) hosts zero apps but runs on dedicated compute, billing while serving nothing. |
Delete the empty {tier} App Service plan. |
N/A (hosted-app count + compute mode) |
|
Application Gateway Idle |
Application Gateways that processed no traffic should be reviewed. |
Mavvrik evaluates gateway traffic over the last complete month. A gateway is flagged when it consumed zero Capacity Units while still billing — the positive bill confirms a real, mature gateway. |
Application Gateway ({tier}) is {state} but consumed zero Capacity Units over the last complete month — it serves no traffic. |
Stop or delete the idle Application Gateway {tier}. |
Capacity Units consumed |
|
Data Factory Idle |
Data Factories that ran no pipelines yet still bill should be reviewed for decommissioning. |
Mavvrik evaluates pipeline activity over a configurable lookback period, with 30 days used by default. A factory is flagged when it ran zero pipelines in that window and in a 60-day confirmation check (so periodic batch factories aren't caught), while still billing. Requires at least 80% coverage. |
Data Factory "{name}" ran no pipelines over the last {N} days (and the {lookback}-day lookback) yet remains provisioned. |
Decommission the unused Data Factory, or pause its provisioned Integration Runtime. |
Succeeded + failed pipeline runs |
|
Data Factory Pipeline Failing |
Data Factories dominated by pipeline failures waste orchestration spend and should be reviewed. |
Mavvrik evaluates pipeline outcomes over a configurable lookback period, with 30 days used by default. A billing factory is flagged when at least 20% of runs fail (or failures occur with zero successes); the failed-run share sizes the wasted spend. |
Data Factory "{name}" is failure-dominated over the last {N} days — {failed} of {total} pipeline runs failed ({rate}%). |
Fix the root cause of the failing pipeline(s), or disable the consistently failing pipeline(s). |
Failed vs total pipeline runs |
|
API Management Idle |
API Management instances serving no traffic yet still billing should be reviewed. |
Mavvrik evaluates gateway activity over a configurable lookback period, with 30 days used by default. An instance is flagged when it received zero requests and capacity load stayed below 1%, while still billing. Requires at least 80% coverage. |
API Management "{name}" ({SKU} tier) is idle — 0 gateway requests and capacity p95 {capacity}% over the last {N} days. |
Decommission the idle API Management instance, or downgrade it to the Consumption tier. |
Gateway requests + capacity load |
|
Disk Snapshot Stale |
Disk snapshots that are orphaned or past retention yet still billing should be reviewed for cleanup. |
Mavvrik evaluates snapshot age and lineage. A snapshot is flagged when it is orphaned (its source disk no longer exists) or stale (older than the retention window, 90 days by default), while still billing. |
Snapshot is orphaned — its source disk no longer exists. It is a {type} {SKU} snapshot with no live source. Or, if stale: Snapshot is stale — created {age} days ago, past the {N}-day retention window. It is a {type} {SKU} snapshot. |
Delete this {orphaned|stale} snapshot. |
N/A (snapshot age + source existence) |
|
SSIS Integration Runtime Non-Production Parking |
Near-idle non-production Azure-SSIS runtimes should be reviewed for an off-hours schedule. |
Mavvrik evaluates runtime usage over a configurable lookback period, with 30 days used by default. A non-production factory's SSIS runtime is flagged when its 95th-percentile CPU is at or below 60% and queue length at or below 5 while it bills node-hours; savings are the off-hours share. |
Non-production Azure-SSIS Integration Runtime is near-idle but bills node-hours continuously - IR CPU p95 {cpu}%, queue-length p95 {queue} over {N} days, ~{node-hours} node-hours/day. |
Schedule the Azure-SSIS Integration Runtime to start at business open and stop at close so it stops billing node-hours off-hours. |
IR CPU % + queue length (95th pct) |
Azure Rightsize Recommendations
Azure resources that may be oversized, underutilized, on a pricier tier / plan / license than needed, or schedulable — candidates for a more cost-effective configuration rather than removal.
|
Recommendation |
Description |
How Recommendation Is Generated |
Reason |
Action |
Metrics |
|---|---|---|---|---|---|
|
Virtual Machine Underutilized |
VMs that are in use but oversized should be reviewed for a smaller size. |
Mavvrik evaluates utilization over a configurable lookback period, with 30 days used by default. A running VM is flagged when its 95th-percentile Max CPU is within 5%–50% (default) and memory at or below 65%. It then recommends the smaller size that keeps projected peak under an 80% headroom guard; scale-set VMs are excluded. |
Virtual Machine is underutilized — CPU p95 {cpu}%, memory p95 {mem}% over the last {N} days. |
Rightsize the Azure VM to a smaller SKU within or across generation in the same series. |
CPU % (95th pct, Max) + memory % + network |
|
Virtual Machine Burstable Candidate |
Steady, low-CPU VMs should be reviewed for a cheaper burstable (B-series) size. |
Mavvrik evaluates CPU over a configurable lookback period, with 30 days used by default. A non-burstable VM is flagged when sustained CPU (95th percentile) is 0%–20% and the absolute peak stays below 40% — a profile the B-series credit model fits. |
Virtual Machine has a steady, low CPU profile — p95 {cpu}%, peak {peak}% over the last {N} days. |
Migrate the Azure VM to a cheaper burstable B-series SKU of the same-or-larger vCPU/memory. |
CPU % (95th pct + peak) |
|
Virtual Machine Generation Modernization |
VMs on an older SKU generation should be reviewed for a newer, cheaper same-size generation. |
A configuration and pricing comparison (no utilization). A running VM on an older generation (2–4 by default) is flagged when a newer same-series generation offers identical vCPU and equal-or-more memory at a lower price. The in-series swap is reservation-safe. |
Virtual Machine runs on superseded generation {SKU} (v{gen}) — a same-size, newer-generation SKU in the same series provides the same vCPU and memory on current-generation hardware. |
Modernize the Azure VM to a newer-generation SKU of the same size in the same series. |
N/A (SKU generation + pricing) |
|
Disk Over-Provisioned |
Disks whose usage sits well below their tier should be reviewed for a cheaper tier. |
Mavvrik evaluates disk IO over a configurable lookback period, with 30 days used by default. An attached disk is flagged when its 95th-percentile IOPS and throughput are at or below 40% of what its tier provisions, and a cheaper target still clears a 99th-percentile peak-headroom guard. |
Managed disk is over-provisioned for its performance tier — p95 {IOPS} IOPS / {MBps} MBps over {N} days. |
Downgrade managed disk to a lower-cost tier or type. |
IOPS + throughput (95th / 99th pct) |
|
SQL DTU Database Underutilized |
DTU databases using far less than their tier provides should be reviewed for a smaller tier. |
Mavvrik evaluates usage over a configurable lookback period, with 30 days used by default. A DTU database still in use (sessions above zero) is flagged when its 95th-percentile DTU is below 20% and storage below 80%. The target tier keeps projected peak under an 80% headroom guard and still holds the stored data. |
SQL database is over-provisioned on its DTU tier — DTU p95 {DTU}%, storage p95 {storage}% over the last {N} days on service objective {SLO}. |
Downgrade the service objective from {current SLO} to {target SLO}. |
DTU % (95th pct) + storage % + sessions |
|
SQL vCore Database Underutilized |
Provisioned-vCore databases using far less than allocated should be reviewed for a smaller size. |
Mavvrik evaluates usage over a configurable lookback period, with 30 days used by default. A provisioned-vCore database still in use is flagged when its 95th-percentile CPU is below 20% and storage below 80%. The target keeps peak under an 80% headroom guard; memory isn't gated, so verify the memory profile first. |
SQL database is over-provisioned on its vCore tier — CPU p95 {cpu}%, storage p95 {storage}% over the last {N} days on {vCores} provisioned vCores ({SLO}). |
Downsize the database from {current vCores} to {target vCores} vCores (service objective {target SLO}). |
CPU % (95th pct) + storage % + sessions |
|
SQL Serverless Database Underutilized |
Serverless databases whose always-billed minimum floor is higher than needed should be reviewed. |
Mavvrik evaluates usage over a configurable lookback period, with 30 days used by default. A serverless database with auto-pause off is flagged when its 95th-percentile used vCores sit below half of its configured minimum-capacity floor; the recommended floor still covers observed demand. |
Serverless SQL database floor is over-provisioned — p95 used {vCores} vCores over {N} days against a {min} vCore minimum capacity. |
Lower the serverless minimum capacity to a floor that still covers observed demand. |
Used vCores (95th pct) + configured floor |
|
MySQL Flexible Server Underutilized |
MySQL Flexible Servers that are in use but oversized should be reviewed for a smaller size. |
Mavvrik evaluates utilization over a configurable lookback period, with 30 days used by default. A GeneralPurpose (non-stopped) MySQL Flexible Server still in use (connections above zero) is flagged when CPU p95 is within 0%–40% and memory p95 at or below 90% (defaults). It then recommends the smaller SKU that keeps projected peak under an 80% headroom guard, preferring an in-family downsize to preserve Reserved Instance coverage. Requires at least 80% coverage. |
MySQL flexible server is over-provisioned - CPU p95 {cpu}%, memory p95 {mem}% over the last {N} days on {SKU} ({vCores} vCores). |
Downsize from {SKU} to {target SKU} within the same compute family (preserves Reserved Instance coverage). If no smaller in-family SKU exists: Re-tier from {SKU} to {target SKU} - no smaller SKU in the compute family, so this leaves the family and may strand Reserved Instance coverage. |
CPU % + memory % (95th pct) + connections |
|
PostgreSQL Flexible Server Underutilized |
PostgreSQL Flexible Servers that are in use but oversized should be reviewed for a smaller size. |
Mavvrik evaluates utilization over a configurable lookback period, with 30 days used by default. A GeneralPurpose (non-stopped) PostgreSQL Flexible Server still in use (connections above zero) is flagged when CPU p95 is within 0%–40% and memory p95 at or below 90% (defaults). It then recommends the smaller SKU that keeps projected peak under an 80% headroom guard, preferring an in-family downsize to preserve Reserved Instance coverage. Requires at least 80% coverage. |
PostgreSQL flexible server is over-provisioned - CPU p95 {cpu}%, memory p95 {mem}% over the last {N} days on {SKU} ({vCores} vCores). |
Downsize from {SKU} to {target SKU} within the same compute family (preserves Reserved Instance coverage). If no smaller in-family SKU exists: Re-tier from {SKU} to {target SKU} - no smaller SKU in the compute family, so this leaves the family and may strand Reserved Instance coverage. |
CPU % + memory % (95th pct) + connections |
|
SQL Database Storage Overallocated |
Databases whose allocated storage far exceeds the data stored should be reviewed. |
Mavvrik evaluates storage usage over a configurable lookback period, with 30 days used by default. A General-Purpose database still in use is flagged when its 95th-percentile storage usage is below 40% of the allocation. The target is used data plus a 30% buffer, never below the data already stored. |
SQL database is over-allocated on storage — only {used}% of the {alloc} GB allocation is used (p95) over the last {N} days, yet the General-Purpose storage meter bills on the full allocation. |
Shrink the storage allocation (maxSizeBytes) from {alloc} GB to about {target} GB. |
Storage % (95th pct) + sessions |
|
Elastic Pool Single Database |
An elastic pool holding one lightly-loaded database pays the pool premium for no benefit. |
Mavvrik evaluates pool usage over a configurable lookback period, with 30 days used by default. A pool holding exactly one database is flagged when compute (below 40%), memory (below 60%), and storage (below 70%) are all low — it pays the pool premium without the sharing benefit. |
Elastic pool contains exactly one member database while billing 24x7 at its provisioned {tier} capacity — the single-database-in-pool anti-pattern (a pool only pays off with 2+ databases). Pool utilisation is low over the last {N} days: compute p95 {compute}%, memory p95 {mem}%, storage p95 {storage}%. |
Migrate the single member database to a standalone single-database SKU and delete the now-empty pool. |
Compute % + memory % + storage % (95th pct) |
|
Elastic Pool Underutilized |
Over-provisioned elastic pools should be reviewed for a smaller capacity on the same tier. |
Mavvrik evaluates pool usage over a configurable lookback period, with 30 days used by default. An active pool is flagged when compute (below 40%), memory (below 60%), and storage (below 70%) are all low — all three must hold, since the memory gate prevents false positives. The smaller target clears an 80% headroom guard. |
Elastic pool is over-provisioned across compute, memory, and storage — compute p95 {compute}%, app-memory p95 {mem}%, storage p95 {storage}% over the last {N} days on {capacity} {unit} ({tier} tier). |
Right-size the elastic pool from {current} to {target} {unit} on the {tier} tier. |
Compute % + memory % + storage % (95th pct) |
|
Elastic Pool Serverless Candidate |
Lightly-used General-Purpose pools that bill a fixed floor 24x7 should be reviewed for serverless. |
Mavvrik evaluates pool usage over a configurable lookback period, with 30 days used by default. A General-Purpose pool is flagged when it runs below 20% CPU for at least 80% of hours with one or fewer sessions, yet isn't fully idle — a fit for a serverless auto-pausing tier. |
Provisioned GP (vCore) elastic pool is idle {idle}% of hours (avg CPU below {cpu}%) over the last {N} days with only p95 {sessions} concurrent sessions, yet bills its fixed vCore floor 24x7. |
Migrate the idle provisioned GP elastic pool to a serverless (GP-vCore) tier with auto-pause. |
Idle-hour share (avg CPU) + sessions |
|
SQL Database Geo-Redundant Backup |
Non-production databases paying for cross-region backup should be reviewed for local backup. |
A configuration and cost check. A non-production database (by tag or name, and not tagged production) on geo-redundant backup is flagged when it pays a positive geo-backup premium; local backup costs about half. |
Non-production SQL database uses geo-redundant backup storage ({current}). Switching to {target} (LRS) removes the cross-region backup premium where DR is not required. |
Change backup redundancy from {current} to {target} on this non-prod database. |
N/A (backup redundancy + geo premium) |
|
App Service Plan Instance Underutilized |
Lightly-used Premium P1v3 App Service plans should be reviewed for a one-step downsize to P0v3. |
Mavvrik evaluates utilization over a configurable lookback period, with 30 days used by default. A P1v3 plan is flagged when its 95th-percentile CPU is below 20% and memory below 50% — the memory gate matters because P0v3 has half the RAM. |
App Service plan (P1v3) is under-utilized — CPU p95 {cpu}% and memory p95 {mem}% over {N} days against a {workers}-worker deployment. |
Downsize the App Service plan from P1v3 to P0v3 (Premium0V3). |
CPU % + memory % (95th pct) |
|
Function App Premium to Flex Consumption |
Under-used Elastic Premium Functions plans should be reviewed for scale-to-zero Flex Consumption. |
Mavvrik evaluates utilization over a configurable lookback period, with 30 days used by default. An Elastic Premium plan is flagged when its 95th-percentile CPU is below 15% and memory below 60%, indicating a scale-to-zero plan may fit. Savings are an estimate. |
Elastic Premium Functions plan ({SKU}, {sites} site(s)) runs at CPU p95 {cpu}% and memory p95 {mem}% over {N} days — below its always-on Premium floor. |
Migrate this Elastic Premium ({SKU}) Functions plan to Flex Consumption (a redeploy, not an in-place tier change). |
CPU % + memory % (95th pct) |
|
API Management Premium to Standard v2 |
Lightly-loaded classic Premium API Management should be reviewed for the cheaper Standard v2 tier. |
Mavvrik evaluates gateway load over a configurable lookback period, with 30 days used by default. A single-region classic Premium instance with no VNet injection is flagged when capacity load stays below 80% — Standard v2 now covers the VNet features that once required Premium. |
API Management is on the classic v1 Premium tier (single-region, capacity p95 {capacity}% over {N} days against a {units}-unit deployment). Classic Premium exists mainly for VNet + multi-region; on the v2 family VNet is now on Standard v2 at a fraction of the price. An advisory re-platform to Standard v2 captures the cost-capability reset. |
ADVISORY: re-platform API Management from classic v1 (Premium) to Standard v2 — a re-deploy + DNS/endpoint cutover + feature-parity check, NOT an in-place tier change. Confirm no classic-only policy / self-hosted-gateway dependency first. |
Capacity load (95th pct) |
|
API Management Non-Production Underutilized |
Non-production Premium API Management should be reviewed for the much cheaper Developer tier. |
Environment is the discriminator. A single-region Premium instance tagged non-production is flagged; the capacity ceiling defaults wide open (100%) and can be tightened. Multi-region instances are excluded because Developer is single-unit. |
API Management is on the Premium tier in a non-production environment ("{env}") — capacity p95 {capacity}% over {N} days on a single-region, {units}-unit deployment. |
Downgrade this non-production API Management instance from Premium to Developer. |
Capacity load (95th pct) |
|
Application Gateway Underutilized |
Application Gateways reserving more minimum instances than needed should be reviewed. |
A configuration and cost check. A gateway is flagged when its minimum instance floor is at or above 2 while carrying reducible capacity-unit spend; the target floor is 1 for production and 0 for non-production (v2 keeps its SLA at a floor of 0). |
Application Gateway ({tier}) reserves a minimum of {current} instances; {target} is sufficient for a {env} workload. |
Lower the Application Gateway minimum instance floor from {current} to {target} ({env}). |
N/A (instance floor + Capacity Units cost) |
|
Application Gateway WAF to Standard |
Non-production WAF-tier Application Gateways should be reviewed for the cheaper Standard tier. |
A configuration and cost check, security-gated. A non-production WAF-tier gateway is flagged when re-pricing its usage at the tenant's own Standard-tier rate yields a saving. The downgrade removes the web application firewall. |
Application Gateway runs the {tier} SKU in a non-production environment. Standard_v2 is the lower-tier SKU without the web application firewall. |
Downgrade this non-production Application Gateway from {tier} to Standard_v2. |
N/A (SKU tier + re-priced billed cost) |
|
Storage Account Geo-Redundant |
Storage accounts paying for cross-region replication with no DR marker should be reviewed. |
A configuration and cost check. An account on a geo-redundant tier with no disaster-recovery tag, at least 30 days old, is flagged when it pays a geo-replication premium. Zone-redundant sources drop to zone-redundant storage; others to local. |
Storage account uses geo-redundant replication ({SKU}) with no DR tag. |
Change redundancy from {current} to {target}. |
N/A (redundancy setting + geo premium) |
|
Storage Account General Purpose v1 |
Legacy general-purpose v1 storage accounts should be reviewed for the cheaper StorageV2 tier. |
A configuration check. A general-purpose v1 account at least 30 days old, still billing for stored data, is flagged. StorageV2 has a lower per-GB rate (and GPv1 retires 13 Oct 2026). |
Storage account is general-purpose v1 (kind=Storage, {SKU}) — GPv2 has lower capacity pricing and the GPv1 kind is deprecated (retires 2026-10-13). |
Upgrade this general-purpose v1 ({SKU}) storage account in place to StorageV2 (GPv2). |
N/A (account kind + stored-data cost) |
|
Log Analytics Workspace Excessive Retention |
Workspaces keeping logs beyond the included window should be reviewed for a shorter period. |
A configuration and cost check. A workspace retaining logs beyond the 90-day included window, and paying the extra-retention charge, is flagged. Production workspaces at or above the 365-day compliance floor are excluded. |
Log Analytics workspace retains logs for {retention} days — well beyond the {included}-day Analytics-plan included window. |
Reduce the workspace interactive retention from {retention} days to {included} days. |
N/A (configured retention + retention cost) |
|
Log Analytics Table Basic Plan Candidate |
Verbose, rarely-queried tables on an Analytics-tier workspace should be reviewed for the Basic plan. |
Mavvrik evaluates the last 30 days. On an Analytics-tier workspace queried fewer than 500 times, a verbose, Basic-eligible table that is at least 5% of ingestion is flagged. Security, audit, and Sentinel tables are excluded; Basic loses some query features. |
The {table} table is ~{share}% of this Analytics-tier (pergb2018) workspace ingestion while the workspace was queried {queries} times over the last {N} days. |
Switch the {table} table to the Basic table plan. |
Per-table ingestion share + query count |
|
Defender CSPM Non-Production |
Paid Defender CSPM on non-production subscriptions should be reviewed. |
Mavvrik evaluates the prior complete month's billing. A non-production subscription (by name) running the paid Defender CSPM plan is flagged; only the paid CSPM meter is targeted and free Foundational CSPM is retained. Security-gated. |
Paid Microsoft Defender CSPM is enabled on non-production subscription "{subscription}"; free Foundational CSPM retains posture visibility. |
Descope the paid Microsoft Defender CSPM plan on this non-production subscription to free Foundational CSPM. |
N/A (Defender CSPM plan + monthly cost) |
|
Defender for Cloud Non-Production |
Paid Defender for Cloud plans on non-production subscriptions should be reviewed. |
Mavvrik evaluates recent Defender billing. A non-production subscription (by name) running a paid Defender plan is flagged, keeping the free Foundational CSPM baseline. Security-gated. |
Paid Defender plan "{plan}" is enabled on non-production subscription "{subscription}". |
Disable or downgrade this paid Microsoft Defender plan on the non-production subscription, keeping free Foundational CSPM. |
N/A (Defender plan + monthly cost) |
|
Defender for Storage Per-Transaction Plan |
Storage accounts on the legacy per-transaction Defender plan should be reviewed for the flat plan. |
Mavvrik evaluates the prior complete month's billing. An account on the per-transaction Defender for Storage plan is flagged when its cost exceeds the flat per-account rate (breakeven derived from the tenant's own flat-plan billing). Protection is unchanged and the switch is reversible. |
Storage account is on the legacy Defender for Storage per-transaction plan, which the new flat per-account plan supersedes (Microsoft is deprecating the per-transaction plan). |
Switch this storage account from the legacy per-transaction Defender for Storage plan to the flat per-account plan. |
Per-transaction cost vs. tenant's flat rate |
|
SQL Server Enterprise to Standard |
Under-used SQL Server Enterprise VMs should be reviewed for the cheaper Standard edition. |
Mavvrik evaluates usage over a configurable lookback period, with 30 days used by default. An Enterprise-licensed SQL Server VM is flagged when its 95th-percentile CPU is below 40% and memory below 60%; savings are the Enterprise-minus-Standard license difference. |
VM ({SKU}) is billing the SQL Server Enterprise license meter but is under-utilized for Enterprise — CPU p95 {cpu}%, memory p95 {mem}% over {N} days. Standard edition would suffice (subject to a guest-side feature check). |
Downgrade the SQL Server edition on this VM from Enterprise to Standard. |
CPU % + memory % (95th pct) |
Azure Orphan Recommendations
Azure resources that are not attached to active workloads and may continue to incur unnecessary costs.
|
Recommendation |
Description |
How Recommendation Is Generated |
Reason |
Action |
|---|---|---|---|---|
|
Disk Unattached |
Managed disks that are detached or attached to a stopped VM bill at the full rate while doing no work. |
A configuration / state check. A managed disk is flagged when it is Unattached, or Reserved (attached to a stopped VM), is not shared, and is at least 7 days old — both states bill at the full rate. |
Managed disk ({SKU}, {size} GiB) is in the {state} state — billing while serving no running VM. |
Snapshot then delete the orphaned managed disk. |
|
Private Endpoint Disconnected |
Private endpoints whose link was severed keep billing while connecting to nothing. |
A configuration / state check. A private endpoint is flagged when its connection is Disconnected or Rejected — a dead link that cannot be re-approved — while its target still exists. |
Private endpoint connection state is {state} for its {target} target — the link was severed and cannot be re-approved (the PE must be recreated to reconnect), yet it keeps billing. |
Delete the disconnected private endpoint (fronted a {target} target). |
|
Private Endpoint Orphaned |
Private endpoints whose target resource has been deleted keep billing while pointing at nothing. |
A configuration / state check. A private endpoint is flagged when its target resource has been deleted (confirmed within a collected subscription). Private-link alias targets and un-ingested subscriptions are excluded to avoid false orphans. |
Private endpoint fronts a {target} target that no longer exists in the asset inventory — it keeps billing while serving a deleted resource. |
Delete the orphan private endpoint (target was {target}). |
|
Public IP Unattached |
Standard static public IPs attached to nothing bill regardless of association. |
A configuration / state check. A public IP is flagged when it is a Standard SKU with a Static allocation and is associated with no resource and no NAT gateway (an IP backing only a NAT gateway is treated as in use and excluded). |
Standard static public IP ({IP}) is associated to neither an ipConfiguration nor a NAT gateway, yet it keeps billing while serving nothing. |
Release the unassociated Standard static public IP ({IP}). |
Azure License Recommendations
Azure resources that may be using a more expensive licensing model than necessary and could benefit from existing licenses or Azure Hybrid Benefit. These recommendations help reduce licensing costs without changing or removing the active workload
|
Recommendation |
Description |
How Recommendation Is Generated |
Reason |
Action |
Metrics |
|
Elastic Pool Hybrid Benefit |
vCore SQL elastic pools paying the bundled SQL license should be reviewed for Azure Hybrid Benefit. |
Mavvrik flags General-Purpose vCore elastic pools still billing the License-Included SQL meter rather than Azure Hybrid Benefit (DTU pools have no separable meter and are excluded). Savings assume Software-Assurance-covered licenses with spare cores, so the recommendation is advisory. |
GP-vCore elastic pool ({SKU}, {vCores} vCores) pays License-Included for its SQL Server licence instead of Azure Hybrid Benefit. |
Apply Azure Hybrid Benefit to this GP-vCore elastic pool (set licenseType to BasePrice). |
N/A (License-Included mode + SQL meter) |
|
SQL Server VM Hybrid Benefit |
SQL Server VMs paying a pay-as-you-go SQL license should be reviewed for Azure Hybrid Benefit. |
Mavvrik flags SQL Server VMs (at least 30 days old) billed pay-as-you-go for the SQL license. Only paid editions qualify — Standard and Enterprise; free editions (Developer, Express, Web, Evaluation) and DR replicas are excluded — and the benefit is modelled on SQL's 4-core-per-VM minimum. Savings assume eligible licenses with active Software Assurance, so the recommendation is advisory. |
SQL VM is paying for a pay-as-you-go SQL Server {edition} license ({cores} cores billable). |
Apply Azure Hybrid Benefit for SQL Server — reuse existing SA-covered SQL Server licenses. |
N/A (SQL edition + license mode; min 4 cores) |
|
SSIS Integration Runtime Hybrid Benefit |
Azure-SSIS runtimes on the pay-as-you-go SQL rate should be reviewed for Azure Hybrid Benefit. |
Mavvrik flags Azure-SSIS runtimes (factory at least 30 days old) billing node-hours on the pay-as-you-go SQL rate rather than Azure Hybrid Benefit; savings are the roughly 40% rate reduction. Assumes eligible Software-Assurance licenses, so the recommendation is advisory. |
Azure-SSIS Integration Runtime bills ~{node-hours} node-hours/day on the pay-as-you-go SQL Server License Included meter instead of Azure Hybrid Benefit. |
Enable Azure Hybrid Benefit on the Azure-SSIS Integration Runtime. |
N/A (SSIS License-Included node-hour meter) |
|
Virtual Machine Windows Hybrid Benefit |
Windows Server VMs paying a pay-as-you-go license should be reviewed for Azure Hybrid Benefit. |
Mavvrik flags running Windows Server VMs (at least 30 days old) still on the pay-as-you-go Windows license rather than Azure Hybrid Benefit; client-desktop and AVD images are excluded. Savings assume the customer holds eligible licenses with active Software Assurance, so the recommendation is advisory. |
Windows Server VM is paying for a pay-as-you-go Windows Server license. |
Apply Azure Hybrid Benefit — set the licenseType to Windows_Server (reuse SA-covered license). |
N/A (Windows Server OS + license mode) |
|
Virtual Machine License Reclaim |
Terminated or stopped VMs still billing a license charge should be reviewed for reclaim. |
Mavvrik flags VMs that are terminated or stop-deallocated (at least 7 days old) yet still bill a Virtual Machines Licenses charge. Only the license meter counts — never compute or disk — so there is no double-count. |
VM is {state} and runs no workload yet keeps billing a Virtual Machines Licenses meter. |
De-scope the VM's license meter. |
N/A (VM state + license meter) |
|
Virtual Machine RHEL PAYG to BYOS |
Red Hat VMs paying the pay-as-you-go RHEL surcharge should be reviewed for bring-your-own-subscription. |
Mavvrik flags running Red Hat marketplace VMs (at least 30 days old) paying the pay-as-you-go RHEL surcharge; a conservative 50% haircut models the realizable saving. Assumes eligible Red Hat subscriptions with Cloud Access, so the recommendation is advisory. |
Running Red Hat VM ({SKU}) pays the pay-as-you-go Red Hat Enterprise Linux license meter instead of bringing its own Red Hat subscription. |
Register the VM's Red Hat subscription in Red Hat Cloud Access and convert it from PAYG RHEL to BYOS (Azure > Configuration > Licensing). |
N/A (RHEL license meter; 50% haircut) |
Recommendations are advisory and support review and decision-making. Thresholds and lookback periods shown are defaults and are configurable per policy. Mavvrik never changes customer cloud resources.