Azure Budget Threshold Alert and Auto-Throttle
On a schedule, the flow reads subscription/resource-group spend versus budget via Azure Resource Manager (Cost Management), alerts owners in Teams and email at 50/80/100% thresholds, and at a configurable cap optionally stops or scales down tagged non-production resources. Logs actions. Prevents budget overruns before the invoice arrives.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
This flow is a daily Azure FinOps guardrail. It reads every Azure Consumption budget for the subscription (current spend vs. configured amount) via Azure Resource Manager (ARM) REST, raises a Teams + email alert when a budget crosses the alert threshold, writes an audit row to Dataverse, and when any budget hits the critical cap it auto-deallocates tagged non-production VMs to stop runaway compute spend — logging each throttle action.
Why it matters: Azure budgets notify, but rarely act. Tiered alerting plus a tag-scoped automatic brake on non-production compute stops budget overruns before the invoice lands, with a full Dataverse audit trail.
State: Ships Off (demo). Going live requires only authorizing the connections, configuring the environment variables (Azure SP credentials, subscription, Teams IDs, recipient), and turning the flow On.
Use Case
A FinOps / platform team wants early, escalating budget warnings and an automatic safety brake on non-production spend when a cap is reached — not a surprise at month end. IT Admins get the Teams alert and the auto-throttle; Finance gets the emailed budget detail and the Dataverse log for reporting.
Flow Architecture
Daily_Budget_Check
Recurrence (Day/1, 07:00 UTC)Runs the budget evaluation once a day
Init_Correlation_Id
Initialize Variable (String)guid() stamped on every log row for traceability
Init_Arm_Base
Initialize Variable (String)ARM base URL from flowlibs_ArmBaseUrl
Init_Subscription_Id
Initialize Variable (String)Target subscription from flowlibs_AzureSubscriptionId
Init_Alert_Threshold
Initialize Variable (Integer = 50)Percent-of-budget at which to alert
Init_Critical_Threshold
Initialize Variable (Integer = 100)Cap percent at which to auto-throttle
Init_Throttle_Tag_Name
Initialize Variable (String = Environment)Tag NAME identifying throttle-eligible resources
Init_Throttle_Tag_Value
Initialize Variable (String = NonProduction)Tag VALUE marking a resource non-production
Init_Cap_Exceeded
Initialize Variable (Boolean = false)Gate flag for the throttle stage
Get_Budgets
HTTP GET (ARM + AAD OAuth)Reads all Microsoft.Consumption/budgets with current spend
For_Each_Budget
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_ArmBaseUrl | String | https://management.azure.com | ARM base URL (reused; sovereign-cloud portable) |
| flowlibs_AzureSubscriptionId | String | <configure> | Target subscription (reused) |
| flowlibs_AzureTenantId | String | <your-tenant-id> | AAD tenant for the service principal (reused) |
| flowlibs_AzureClientId | String | <configure> | Service-principal app id (reused) |
| flowlibs_AzureClientSecret | String | <configure> | Service-principal secret (reused) |
| flowlibs_BudgetApiVersion | String | 2023-11-01 | Consumption budgets REST API version (new) |
| flowlibs_ComputeApiVersion | String | 2023-04-02 | Compute REST API version for VM list/deallocate (reused) |
| flowlibs_TeamsGroupId | String | <your-team-id> | Teams team/group id for alerts (reused) |
| flowlibs_TeamsChannelId | String | <your-channel-id> | Teams channel id for alerts (reused) |
| flowlibs_BudgetAlertRecipient |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| Microsoft Teams | shared_teams | PostMessageToConversation |
| Office 365 Outlook | shared_office365 | SendEmailV2 |
| Microsoft Dataverse | shared_commondataserviceforapps | CreateRecord |
Note — All connections are referenced as solution connection references; the flow is portable between environments as long as a connection is mapped at import time.
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Warn tier (80%)
- Add a middle Init_Warn_Threshold and a branch for an info-level alert before the critical cap.
- Forecast-based alerting
- Read currentSpend + forecastSpend from the budget object and alert on projected month-end overspend.
- Approval before throttle
- Insert an Approvals StartAndWaitForAnApproval in Check_Cap_Exceeded so a human authorizes the deallocate instead of it being automatic.
- Scale instead of stop
- Swap Deallocate_VM for a VM resize, or extend the filter to disks / App Service plans for broader throttling.
- Per-RG budgets
- Budgets already carry a scope; group/route alerts by resource group or owner tag.
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01Percent used (Compose_Percent_Used)
Computes the percent of budget consumed, guarding against divide-by-zero.
EXPR.02Alert gate
True when percent used reaches the alert threshold.
EXPR.03Integer percent for Dataverse
Truncates the percent to an integer for the audit log column.
EXPR.04Tag filter (Filter_NonProd_VMs)
Keeps VMs whose throttle tag matches the non-production value.
EXPR.05Deallocate URI
Builds the ARM deallocate endpoint for the current VM.
EXPR.06ARM OAuth audience
Derives the OAuth audience from the ARM base URL.
Customize & download
Generate a ready-to-import copy of this solution with your environment-variable values baked in — available on Base, Pro, or Team.
Upgrade to customize
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.