Azure Advisor - Delete a recommendation suppression
- Intro
- Why a normal Bicep deployment can’t delete this resource
- Delete with PowerShell
- Delete with az CLI
- Verify the suppression is gone
- Adapting this into a pipeline
Intro
This article is part of a series: Navigate to series page
In this post I show how to delete an Azure Advisor recommendation suppression, which brings the recommendation back into an active state again. Unlike create and update, I don’t reach for a plain Bicep deployment here - I’ll explain why, and show the approach I actually use.
Why a normal Bicep deployment can’t delete this resource
Standard (incremental mode) Bicep/ARM deployments only ever add or update resources that are present in the template - they never remove a resource just because you deleted its declaration from the file. To get deletion behavior from a template-based deployment, you’d need either:
- A complete mode deployment at the resource’s scope, which deletes any resource in that scope not present in the template - far too destructive to use just to remove one suppression.
- An Azure Deployment Stack with
--action-on-unmanage deleteResources(theactionOnUnmanageproperty in ARM/Bicep terms), which tracks exactly the resources it deployed and can safely remove ones no longer in the template.
If you’re already managing suppressions through a deployment stack (recommended if you’re creating several), removing a suppression’s resource block from the Bicep file and redeploying the stack with resource cleanup enabled will delete it cleanly:
az stack sub create `
--name advisor-suppressions-stack `
--location westeurope `
--template-file ./suppressions.bicep `
--deny-settings-mode none `
--action-on-unmanage deleteResources
If you’re deploying suppressions as plain (non-stack) Bicep templates - which is what Part 3 and Part 4 of this series used for simplicity - the practical option is to call the Advisor REST API directly for deletion, the same way az rest/Invoke-RestMethod is already used elsewhere in this series for read operations.
Delete with PowerShell
Connect-AzAccount
$subscriptionId = (Get-AzContext).Subscription.Id
$secureToken = (Get-AzAccessToken -ResourceUrl "https://management.azure.com/").Token
$token = ConvertFrom-SecureString -SecureString $secureToken -AsPlainText
$headers = @{ "Authorization" = "Bearer $token" }
$apiVersion = "2023-01-01"
$recommendationId = "a1b2c3d4-1111-2222-3333-444455556666"
$suppressionName = "reserved-instance-cost-suppression"
# For endpoint details, see:
# https://learn.microsoft.com/en-us/rest/api/advisor/suppressions/delete
$uri = "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Advisor/recommendations/$recommendationId/suppressions/$($suppressionName)?api-version=$apiVersion"
Invoke-RestMethod -Uri $uri -Method Delete -Headers $headers
A successful delete returns an empty 204 No Content response.
Delete with az CLI
$subscriptionId = "00000000-0000-0000-0000-000000000000"
$recommendationId = "a1b2c3d4-1111-2222-3333-444455556666"
az rest `
--method delete `
--url "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Advisor/recommendations/$recommendationId/suppressions/reserved-instance-cost-suppression?api-version=2023-01-01"
For a resource-scoped suppression (like the VM high-availability example from Part 3), swap the subscription-scoped path for the full resource path:
az rest `
--method delete `
--url "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/rg-avd-prod/providers/Microsoft.Compute/virtualMachines/vm-avd-01/providers/Microsoft.Advisor/recommendations/$recommendationId/suppressions/high-availability-suppression?api-version=2023-01-01"
Verify the suppression is gone
Re-run the list script from Part 2, or check the recommendation’s status directly - it should now show as Active again in the Azure portal instead of Postponed/Dismissed.
Adapting this into a pipeline
- Keep a source-controlled list of active suppressions (recommendation, resource, justification, review date), as suggested in Part 4.
- When an entry is removed from that list (justification expired, issue fixed, etc.), have your pipeline call the delete REST API for that specific recommendation/suppression name pair as a cleanup step, rather than trying to force it through a plain Bicep deployment.
- If you manage suppressions exclusively through deployment stacks, prefer
actionOnUnmanage: deleteResourcesso removal is driven entirely by the Bicep file and pull request diff, with no separate REST call needed.
That covers the full lifecycle - getting, creating, updating, and deleting suppressions. If you skipped it, Part 1 - Known limitations is worth reading before you build this into a real pipeline, since it covers the scope, lifetime, and inheritance caveats that shape how you should design around all four operations in this series.
Navigate back to the series page
Have feedback on this post?
Send me a message and I'll get back to you.