Image of a Playmobil garbage man by jacqueline macou -

As I described in a previous post on ephemeral workloads, I separate experiments into their own resource groups and like to automate all provisioning to make sure they’re repeatable and delete-able.

I saw this tweet from Jeff Hollan the other day and it gave me the foundation to create a garbage collector for my experiments using Powershell Azure Functions. This makes a good example of Azure management automation using Functions.

The concept is great! Since I’m already using a purpose tag to identify transient workload I want to piggy-back on that. I also want to be able to keep resource groups longer than just one day. My garbage collector needs to:

  1. Automatically assign a purpose1 if it’s missing.
  2. For resource groups with a tag purpose set to experiment, add an expiry date automatically, two weeks from now
  3. Delete groups with an expiry tag once it’s in the past
  4. Send me notification to make sure things aren’t marked for deletion erroneously.

To do so I’m using a combination of Powershell Azure Functions to tag and remove the resources, and LogicApp to send notifications. The solution (including a provisioning script that can be ran to deploy everything to your own subscription) is on GitHub.


Functions in the Azure Portal

The function app contains three functions:

  1. AddPurpose runs every hour and adds a purpose tag if none is set.
  2. AddExpiryDate runs every hour and adds an expiry tag in 2 weeks if none is set.
  3. CleanupExpired runs once a day at UTC+8 (PT), and deletes all resource groups where expiry is in the past.

All functions send a message to a queue when they do something.

Those functions are relatively simple. Let’s look at CleanupExpired for example:

Select the subscription and query expired resource groups:

Write-Host "Garbage collection triggered at $date"
Select-AzSubscription -Subscription $env:SUBSCRIPTION
$expiredResources = Get-AzResourceGroup | Where-Object { $_.Tags.expiry -and [DateTime] $_.Tags.expiry -lt $date }

Iterate through resource groups and delete them:

Foreach ($resourceGroup in $expiredResources) {
    Write-Host "Collecting $($resourceGroup.ResourceGroupName)"
    Remove-AzResourceGroup -Name $resourceGroup.ResourceGroupName -Force

Send a message to the queue (using a queue binding):

    $evt = [ordered]@{
    $jsonEvent = $evt | ConvertTo-Json -Depth 10
    Push-OutputBinding -Name "eventsQueue" -Value $jsonEvent
Write-Host "Done collecting"


The logic app uses the queue connector to retrieve messages to be sent:

View of the notification logicapp

Based on the type, a different message is assembled, then it uses the O365 connector to send an email.

I'm sending myself emails


All the code is here.


  1. Purpose being: experiment, production, development, etc.