In the dynamic landscape of cloud computing, optimizing cloud cost is the most important factor for businesses when they deploy their workloads on major cloud platforms like Microsoft Azure. By default, they offer various features to manage cloud resource costs efficiently. However, the most impactful strategy is to reduce Azure costs by shutting down idle resources during off-hours. This strategy helps organizations cut down on unnecessary expenses while ensuring resources are available when needed.
In this article, I will walk you through some benefits of automating Azure idle resource shutdown and a step-by-step approach to implementing Azure Automation with Runbooks for major resources like Application Gateways in your Azure environment.
Why Shutting Down Azure Idle Resources?
As you may already know Azure’s pay-as-you-go subscription model charges users based on resource consumption. That simply means once you deploy any Azure resource it starts to incur cost. Most of the time these resources continue running even during non-business hours, on weekends, or when they’re not actively utilized.
The concept of resource shutdown revolves around the idea of turning off or scaling down these resources when they’re not needed. For instance, non-production environments like development or testing databases often remain idle outside of working hours. Similarly, certain applications or services might not require continuous operation.
Methods for Automating Azure Resource Shutdown
Azure Automation with Runbooks
Azure Automation provides a robust framework for scheduling and automating resource shutdown. Using runbooks organizations can create schedules to start and stop resources at predefined times.
Azure Logic Apps
Azure Logic Apps offer a low-code solution for automating resource shutdowns based on predefined schedules, conditions, or external triggers, such as Azure Monitor, Cost Management, Microsoft Teams, or email notifications. This enables more intelligent automation than basic scheduled tasks.
Azure DevOps Pipelines
If you manage infrastructure as code (IaC), Azure DevOps Pipelines can be used to schedule shutdown tasks for better cost optimization.
Step-by-Step Guide to Automating Azure Idle Resource Shutdown
Create an Azure Automation Account
Navigate to the Azure portal, search for “Automation Accounts” and create a new account. During the creation, make sure to select the appropriate Azure subscription and the resource group. Assign a meaningful name and choose the desired region.

In the Advanced tab, set the Managed Identity to “System assigned“. Leave the remaining tabs with default settings and create the automation account.

Create a Custom Role and Configure the Identity
Create an Azure Custom Role for Subscription
Go to your Azure subscription settings, and select “Access control (IAM)” from the left-hand menu. Click on “Add”, then select “Add custom role“.

Go to the Permissions tab and click “Add permissions“. Search the following for the required Azure Resource Provider and select specific permissions. Finally, click “Add” to include them in your role.
- Microsoft.Network/applicationGateways/start/action
- Microsoft.Network/applicationGateways/stop/action

Leave the remaining settings unchanged and proceed to create the custom role.
Configure the Automation Account Identity
Once the custom role is ready, navigate to the Automation Account Identity section and click the “Azure role assignments“.

Assign the previously created custom role and the Subscription Reader role to the resource group where the Azure Application Gateway is located. This will enable the Automation Account to initiate start and stop operations on the Azure Application Gateway.

Create a Runbook
In this step, you can create multiple runbooks for your desired Application Gateway operations. For this demo, I will create a runbook to shut down the Azure Application Gateway.
In your Automation Account, go to “Runbooks” and select “Create a runbook.”

Choose “PowerShell” as the runbook type and appropriate runtime version. Then create the runbook.

After creating the runbook, the code editor will open automatically for entering the PowerShell script. Modify the $subscriptionId, $resourceGroupName, and $applicationGatewayName according to your requirement and paste the following script on the editor.
# Provide your Azure subscription ID and resource group name
$subscriptionId = "2cdtb582-3271-13eb-8401-07140s2acq4p"
$resourceGroupName = "rg-automation-demo"
$applicationGatewayName = "agw-demo"
try
{
"Logging in to Azure..."
Connect-AzAccount -Identity
}
catch {
Write-Error -Message $_.Exception
throw $_.Exception
}
# Get the Application Gateway
$applicationGateway = Get-AzApplicationGateway -Name $applicationGatewayName -ResourceGroupName $resourceGroupName
if ($applicationGateway) {
$operationalState = $applicationGateway.OperationalState
Write-Output "Application Gateway '$applicationGatewayName' operational state: $operationalState"
if ($operationalState -eq "Running") {
Write-Output "Application Gateway '$applicationGatewayName' is already running. Proceeding to stop..."
# Stop the Application Gateway
Stop-AzApplicationGateway -ApplicationGateway $applicationGateway
Start-Sleep -Seconds 10
Write-Output "Application Gateway '$applicationGatewayName' stopping. Waiting for it to stop..."
$gatewayStopped = $false
while (-not $gatewayStopped) {
$applicationGateway = Get-AzApplicationGateway -Name $applicationGatewayName -ResourceGroupName $resourceGroupName
if ($applicationGateway) {
$operationalState = $applicationGateway.OperationalState
Write-Output "Application Gateway '$applicationGatewayName' operational state: $operationalState"
if ($operationalState -eq "Stopped") {
Write-Output "Application Gateway '$applicationGatewayName' is stopped."
$gatewayStopped = $true
} else {
Write-Output "Application Gateway is still not stopped. Waiting for 10 seconds before rechecking..."
Start-Sleep -Seconds 10
}
} else {
Write-Output "Application Gateway '$applicationGatewayName' not found in resource group '$resourceGroupName'."
$gatewayStopped = $true
}
}
Write-Output "Application Gateway '$applicationGatewayName' has been successfully stopped."
} else {
Write-Output "Application Gateway '$applicationGatewayName' is not in a running state. No action required."
}
} else {
Write-Output "Application Gateway '$applicationGatewayName' not found in resource group '$resourceGroupName'."
}

After confirming that all configurations are correct, click Save to store the changes and then select Publish to make the runbook available for execution. Once published, you can initiate the runbook to test its functionality and ensure it runs as expected.

You can monitor the execution and review the log output of the runbook by navigating to the Runbook Jobs section. This provides detailed information about the job’s status, execution history, and any potential errors or messages generated during the process.

To verify the operational status of the Azure Application Gateway, navigate to its Properties section in the Azure portal. Here, you can review key details such as its provisioning state, operational status, and other relevant metrics to ensure it is functioning correctly.

Schedule the Runbook
After successfully testing the runbook manually, you can schedule it to run at a specific date and time based on your requirements. Alternatively, for greater flexibility, you can integrate it with Azure Logic Apps to trigger executions dynamically based on predefined conditions. In this case, I will proceed with configuring a scheduled execution for the created runbook.
In the same runbook that you created previously, select the Schedules sections and Add a schedule.

Then click the “Link a schedule to your runbook” option and add the schedule.

In the same way, you can create another runbook to start the Azure Application Gateway. Follow the same process for runbook creation and use the code snippet provided below.
Azure Application Gateway Start Code
# Provide your Azure subscription ID, resource group name, and application gateway name
$subscriptionId = "2cdtb582-3271-13eb-8401-07140s2acq4p"
$resourceGroupName = "rg-automation-demo"
$applicationGatewayName = "agw-demo"
try
{
"Logging in to Azure..."
Connect-AzAccount -Identity
}
catch {
Write-Error -Message $_.Exception
throw $_.Exception
}
# Get the Application Gateway
$applicationGateway = Get-AzApplicationGateway -Name $applicationGatewayName -ResourceGroupName $resourceGroupName
if ($applicationGateway) {
$operationalState = $applicationGateway.OperationalState
Write-Output "Application Gateway '$applicationGatewayName' operational state: $operationalState"
if ($operationalState -eq "Stopped") {
Write-Output "Application Gateway '$applicationGatewayName' is currently stopped. Proceeding to start..."
# Start the Application Gateway
Start-AzApplicationGateway -ApplicationGateway $applicationGateway
Start-Sleep -Seconds 10
Write-Output "Application Gateway '$applicationGatewayName' starting. Waiting for it to start..."
$gatewayStarted = $false
while (-not $gatewayStarted) {
$applicationGateway = Get-AzApplicationGateway -Name $applicationGatewayName -ResourceGroupName $resourceGroupName
if ($applicationGateway) {
$operationalState = $applicationGateway.OperationalState
Write-Output "Application Gateway '$applicationGatewayName' operational state: $operationalState"
if ($operationalState -eq "Running") {
Write-Output "Application Gateway '$applicationGatewayName' is running."
$gatewayStarted = $true
} else {
Write-Output "Application Gateway is still not running. Waiting for 10 seconds before rechecking..."
Start-Sleep -Seconds 10
}
} else {
Write-Output "Application Gateway '$applicationGatewayName' not found in resource group '$resourceGroupName'."
$gatewayStarted = $true
}
}
Write-Output "Application Gateway '$applicationGatewayName' has been successfully started."
} else {
Write-Output "Application Gateway '$applicationGatewayName' is already running. No action required."
}
} else {
Write-Output "Application Gateway '$applicationGatewayName' not found in resource group '$resourceGroupName'."
}
Conclusion
Automating Azure idle resource shutdown is an effective way to reduce cloud costs without compromising performance. By leveraging Azure Automation, Logic Apps, and other automation tools, businesses can significantly lower their Azure bills while ensuring optimal resource utilization.