From Aggregate Numbers to Actionable Breakdowns
Knowing that your Azure bill was $147,000 last month tells you almost nothing useful. Was it compute or storage that drove the total? Which team’s resource group caused the $12,000 spike? Is the database tier costing more than the application tier it supports? Breaking costs down by resource group and service transforms a single number into a map of where money flows — and that map is what makes optimization, chargeback, and budget ownership possible.
Azure Cost Management provides multiple mechanisms for slicing costs along these dimensions, from interactive portal views to programmatic APIs that feed automated reports. This guide covers the full spectrum: portal-based analysis for quick investigations, REST API and PowerShell queries for automated breakdowns, cost allocation rules for distributed shared costs, and tagging strategies that make breakdowns meaningful from day one.
Breaking Down Costs in the Azure Portal
The fastest path to a cost breakdown lives in Cost Analysis. Navigate to Cost Management + Billing → Cost Management → Cost analysis and select your scope — subscription, resource group, or billing account.
Using the Group By Selector
In any customizable view (Accumulated costs, Daily costs, Cost by service), the Group by dropdown lets you segment the chart and table by a single dimension. The most useful dimensions for cost breakdowns include:
| Dimension | What It Shows | Useful For |
|---|---|---|
| Resource group | Costs aggregated by resource group | Team-level chargeback, application cost tracking |
| Service name | Azure service classification (Compute, Storage, Networking) | Understanding which service categories drive spend |
| Service family | High-level service type (Compute, Analytics, Security) | Executive-level service category views |
| Resource type | Specific resource types (Microsoft.Compute/virtualMachines) | Identifying which resource types cost the most |
| Location | Azure region | Regional cost comparison, identifying expensive regions |
The chart displays the top 10 contributors as distinct segments. Everything beyond the top 10 rolls into an “Others” category. To drill deeper, click any segment to apply it as a filter, then regroup by a second dimension. For example, group by Resource group, click the most expensive group, then regroup by Service name to see what services drive that group’s costs.
Smart Views for Pre-Built Breakdowns
The smart views in Cost Analysis provide ready-made breakdowns that require no configuration:
- Resource groups — Automatically aggregates costs by resource group with drill-down capability. Expand any row to see the next level of detail. Select a resource group name to navigate directly into its cost breakdown.
- Services — Groups costs by Azure service, matching the Invoice details view but organized by service hierarchy rather than billing line items.
- Resources — Lists individual resources with their costs, including deleted resources whose charges are still appearing. This view includes anomaly detection indicators that flag resources with unusual spending.
Smart views also display KPI tiles at the top: total cost with percentage change versus the prior period, and average cost with a trend indicator. These provide immediate context for whether the breakdown you are looking at is trending up, down, or stable.
Portal Limitations
One significant limitation: customizable views support only one Group By dimension at a time. You cannot simultaneously group by resource group and service in a single portal view. For two-dimensional breakdowns (cost by resource group AND service in a single table), you need the REST API, PowerShell, or exported data in a tool like Power BI.
Programmatic Cost Breakdowns with the REST API
The Cost Management Query API supports up to two simultaneous grouping dimensions, enabling cross-dimensional breakdowns that the portal cannot produce in a single view.
Single-Dimension Grouping: Costs by Resource Group
POST https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.CostManagement/query?api-version=2025-03-01
{
"type": "ActualCost",
"timeframe": "TheLastMonth",
"dataset": {
"granularity": "None",
"aggregation": {
"totalCost": {
"name": "PreTaxCost",
"function": "Sum"
}
},
"grouping": [
{
"name": "ResourceGroup",
"type": "Dimension"
}
]
}
}
This returns a flat list of every resource group in the subscription with its total cost for the last month. The granularity: "None" setting produces a single aggregate per group rather than daily or monthly breakpoints.
Two-Dimension Grouping: Costs by Resource Group and Service
{
"type": "ActualCost",
"timeframe": "TheLastMonth",
"dataset": {
"granularity": "None",
"aggregation": {
"totalCost": {
"name": "PreTaxCost",
"function": "Sum"
}
},
"grouping": [
{
"name": "ResourceGroup",
"type": "Dimension"
},
{
"name": "ServiceName",
"type": "Dimension"
}
]
}
}
This produces a matrix of resource group plus service combinations — exactly the cross-tabulation that tells you which services cost the most within each team’s resource group. The API supports a maximum of two grouping clauses per query.
Filtered Breakdown: Specific Resource Groups by Service
{
"type": "ActualCost",
"timeframe": "MonthToDate",
"dataset": {
"granularity": "Daily",
"aggregation": {
"totalCost": {
"name": "PreTaxCost",
"function": "Sum"
}
},
"grouping": [
{
"name": "MeterCategory",
"type": "Dimension"
}
],
"filter": {
"dimensions": {
"name": "ResourceGroup",
"operator": "In",
"values": ["rg-webapp-prod", "rg-api-prod"]
}
}
}
}
This filters to specific resource groups and then breaks down their daily costs by meter category, showing exactly how each service contributes to the filtered groups’ spending over time.
PowerShell Automation for Cost Breakdowns
The Az.CostManagement module wraps the Query API into PowerShell cmdlets, making it straightforward to build scheduled breakdown reports.
Cost by Resource Group — Last Month
# Create grouping objects
$groupByRG = New-AzCostManagementQueryGroupingObject `
-Name 'ResourceGroup' -Type 'Dimension'
# Run the query
$result = Invoke-AzCostManagementQuery `
-Scope "/subscriptions/your-subscription-id" `
-Timeframe TheLastMonth `
-Type ActualCost `
-DatasetGrouping @($groupByRG) `
-DatasetAggregation @{
"totalCost" = @{ "name" = "PreTaxCost"; "function" = "Sum" }
}
# Format output
$result.Row | ForEach-Object {
[PSCustomObject]@{
Cost = [math]::Round($_[0], 2)
ResourceGroup = $_[1]
Currency = $_[2]
}
} | Sort-Object Cost -Descending | Format-Table -AutoSize
Two-Dimensional Breakdown: Resource Group by Service
$groupByRG = New-AzCostManagementQueryGroupingObject `
-Name 'ResourceGroup' -Type 'Dimension'
$groupBySvc = New-AzCostManagementQueryGroupingObject `
-Name 'ServiceName' -Type 'Dimension'
$result = Invoke-AzCostManagementQuery `
-Scope "/subscriptions/your-subscription-id" `
-Timeframe TheLastMonth `
-Type ActualCost `
-DatasetGrouping @($groupByRG, $groupBySvc) `
-DatasetAggregation @{
"totalCost" = @{ "name" = "PreTaxCost"; "function" = "Sum" }
}
# Output as CSV for further analysis
$result.Row | ForEach-Object {
[PSCustomObject]@{
Cost = [math]::Round($_[0], 2)
ResourceGroup = $_[1]
ServiceName = $_[2]
Currency = $_[3]
}
} | Export-Csv -Path "cost-breakdown.csv" -NoTypeInformation
This script produces a CSV file with every resource group and service combination, ready for pivot tables, chargeback calculations, or ingestion into a dashboard.
Cost Allocation Rules for Shared Resources
Not every cost maps cleanly to a single resource group. Shared infrastructure — a centralized API gateway, a shared database server, common monitoring tools — generates costs that belong to multiple teams. Cost allocation rules let you distribute these shared costs proportionally.
How Cost Allocation Works
Navigate to Cost Management + Billing → Cost Management → Settings → Configuration → Cost allocation. This feature requires an Enterprise Agreement or Microsoft Customer Agreement with Enterprise scope.
Cost allocation rules have three components:
- Sources — The subscriptions, resource groups, or tags whose costs should be distributed. These are your shared infrastructure costs.
- Targets — The subscriptions, resource groups, or tags that receive the allocated costs. These are the consuming teams or applications.
- Allocation method — How to split the costs across targets.
Six allocation methods are available:
| Method | Logic |
|---|---|
| Distribute evenly | Equal percentage to all targets |
| Total cost | Proportional to each target’s total Azure cost |
| Compute cost | Proportional to Microsoft.Compute resources |
| Storage cost | Proportional to Microsoft.Storage resources |
| Network cost | Proportional to Microsoft.Network resources |
| Custom | Manual percentages (must total 100%) |
After creating a rule, allocated costs appear in Cost Analysis when you group by the “Cost allocation” dimension. The allocation data also appears in cost exports and the Cost Details API, including a costAllocationRuleName column that identifies which rule applied. Rules can take up to 24 hours to take effect, and they do not affect the actual billing invoice — they are purely for internal visibility and chargeback purposes.
Tagging Strategy for Meaningful Breakdowns
Resource groups provide a structural cost boundary, but tags provide flexible cost attribution that crosses structural boundaries. A virtual machine in the shared-infrastructure resource group can carry a costcenter tag that assigns its cost to the business unit that benefits from it.
Essential Tags for Cost Attribution
The Azure Cloud Adoption Framework recommends these tags for cost management:
| Tag Key | Purpose | Example Values |
|---|---|---|
| costcenter | Financial cost center for chargeback | 55332, CC-10045 |
| department | Business department | engineering, marketing, finance |
| environment | Deployment environment | prod, dev, qa, stage |
| app | Application name | catalog-api, payment-service |
| businessunit | Organizational business unit | retail, corporate, shared-services |
| criticality | Business criticality tier | mission-critical, medium, low |
Tag names in Azure are case-insensitive but tag values are case-sensitive. Inconsistent casing — tagging some resources with “Production” and others with “production” — fragments your cost breakdown into separate categories. Establish a convention (all lowercase is the simplest) and enforce it through Azure Policy.
Grouping by Tag in the Query API
{
"type": "ActualCost",
"timeframe": "TheLastMonth",
"dataset": {
"granularity": "None",
"aggregation": {
"totalCost": {
"name": "PreTaxCost",
"function": "Sum"
}
},
"grouping": [
{
"name": "CostCenter",
"type": "Tag"
}
]
}
}
Note the type property in the grouping object is Tag (aliased as TagKey) rather than Dimension. This groups costs by whatever value each resource carries for the specified tag. Resources without the tag appear in a null or unassigned category — which is itself useful information when tracking tagging compliance.
Tag Inheritance in Cost Management
By default, cost records only include tags that are directly applied to the resource. A resource inside a tagged resource group does not automatically inherit the group-level tags in cost reports. Enable tag inheritance in Cost Management settings to propagate subscription-level and resource group-level tags to the usage records of child resources. This significantly improves the coverage of tag-based cost breakdowns without requiring every individual resource to be tagged.
Resource Group Naming Conventions That Help Cost Analysis
When resource groups follow a consistent naming convention, cost breakdowns become self-documenting. A well-named resource group tells you the workload, environment, and sometimes the team — without needing to look up metadata.
The Cloud Adoption Framework recommends patterns like:
rg-webapp-prod— Application name plus environmentrg-analytics-prod-eastus— Application, environment, and regionrg-shared-networking-prod— Shared infrastructure with functional description
Embedding the environment name (prod, dev, qa) in the resource group name makes environment-level cost breakdowns possible through simple string matching, even without tags. When reviewing a cost-by-resource-group chart, you can immediately distinguish production costs from development costs by scanning the names.
Building Automated Breakdown Reports
Combining the PowerShell query approach with scheduling produces recurring cost breakdown reports that land in inboxes or Teams channels without manual effort.
# Automated monthly cost breakdown report
$scope = "/subscriptions/your-subscription-id"
$groupByRG = New-AzCostManagementQueryGroupingObject -Name 'ResourceGroup' -Type 'Dimension'
$result = Invoke-AzCostManagementQuery `
-Scope $scope -Timeframe TheLastMonth -Type ActualCost `
-DatasetGrouping @($groupByRG) `
-DatasetAggregation @{ "totalCost" = @{ "name" = "PreTaxCost"; "function" = "Sum" } }
$report = $result.Row | ForEach-Object {
[PSCustomObject]@{
ResourceGroup = $_[1]
Cost = [math]::Round($_[0], 2)
Currency = $_[2]
}
} | Sort-Object Cost -Descending
# Calculate total and percentages
$total = ($report | Measure-Object -Property Cost -Sum).Sum
$report | ForEach-Object {
$_ | Add-Member -NotePropertyName 'Percentage' -NotePropertyValue ([math]::Round($_.Cost / $total * 100, 1))
}
$report | Format-Table -AutoSize
This script produces a sorted breakdown with percentage contribution for each resource group. Wrap it in an Azure Automation runbook or a GitHub Actions workflow that runs on the 3rd of each month (after charges finalize), and pipe the output to email or a shared storage location.
Practical Recommendations
Start with the portal smart views for immediate visibility. The Resource groups view gives you a one-click breakdown that requires zero setup. Bookmark it and make it part of your weekly FinOps review.
For cross-dimensional analysis that the portal cannot provide in a single view, use the Query API with two grouping dimensions. The combination of ResourceGroup and ServiceName answers the most common chargeback question: which services are each team spending money on?
Invest in tagging before you invest in complex allocation rules. A well-tagged environment makes cost breakdowns natural — every query, view, and export can slice by tag. Cost allocation rules are powerful but complex; save them for genuinely shared costs that cannot be attributed through tags or resource group structure.
Name your resource groups deliberately. The few seconds spent choosing a descriptive, convention-following name pays dividends every time someone reviews a cost breakdown chart. When rg-webapp-prod appears in a cost report, everyone knows what it is. When ResourceGroup1 appears, someone has to look it up, and more often than not, nobody does.
The goal of cost breakdowns is not the data itself — it is the decisions the data enables. A resource group consuming 40 percent of subscription costs deserves a deeper look. A service growing at 20 percent month-over-month needs a conversation about whether that growth is intentional. The breakdown is the starting point for those conversations, and the more accessible and automated you make it, the more frequently those conversations happen.
For more details, refer to the official documentation: What is Microsoft Cost Management.