Tagging and Cost Allocation Strategy
Design and enforce resource tagging strategies for cloud cost visibility. Covers mandatory tag schemas, tag enforcement in IaC, cost allocation reports, tag governance, and the patterns that make cloud spend attributable to teams, products, and environments.
Without tags, your cloud bill is a lump sum. With tags, it becomes a detailed ledger: this team spent X, this product costs Y, this environment wastes Z. Tagging is the simplest FinOps practice with the highest leverage — and the most frequently botched.
Tag Schema Design
# Mandatory tags (enforced via policy)
mandatory_tags:
team:
description: "Engineering team that owns this resource"
allowed_values: ["payments", "identity", "platform", "data", "ml"]
enforcement: "DENY creation without tag"
environment:
description: "Deployment environment"
allowed_values: ["production", "staging", "development", "sandbox"]
service:
description: "Application or microservice name"
format: "lowercase-with-hyphens"
examples: ["order-api", "user-service", "payment-processor"]
cost_center:
description: "Finance cost center code"
format: "CC-XXXX"
examples: ["CC-1001", "CC-2050"]
# Recommended tags (not enforced but encouraged)
recommended_tags:
project:
description: "Project or initiative"
examples: ["q1-migration", "new-checkout", "compliance-2024"]
managed_by:
description: "How the resource is managed"
allowed_values: ["terraform", "pulumi", "manual", "cdk"]
data_classification:
description: "Data sensitivity level"
allowed_values: ["public", "internal", "confidential", "restricted"]
Tag Enforcement
# AWS: Service Control Policy to enforce mandatory tags
scp_enforce_tags = {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyUntaggedEC2",
"Effect": "Deny",
"Action": [
"ec2:RunInstances",
"ec2:CreateVolume",
],
"Resource": "*",
"Condition": {
"Null": {
"aws:RequestTag/team": "true",
"aws:RequestTag/environment": "true",
"aws:RequestTag/service": "true",
}
}
}
]
}
# Terraform: Module-level tag enforcement
# modules/base/variables.tf
variable "required_tags" {
type = object({
team = string
environment = string
service = string
cost_center = string
})
validation {
condition = contains(["payments", "identity", "platform", "data", "ml"], var.required_tags.team)
error_message = "Team must be one of: payments, identity, platform, data, ml."
}
}
# All resources inherit tags
locals {
common_tags = merge(var.required_tags, {
managed_by = "terraform"
created_at = timestamp()
})
}
Cost Allocation Reports
class CostAllocationReport:
def generate_team_breakdown(self, period="month"):
"""Cost breakdown by team tag."""
costs = self.billing.get_costs_by_tag("team", period)
return {
"period": period,
"total": sum(costs.values()),
"by_team": {
team: {
"total": cost,
"pct_of_total": cost / sum(costs.values()) * 100,
"mom_change": self.calculate_mom_change(team, cost),
}
for team, cost in sorted(costs.items(), key=lambda x: -x[1])
},
"untagged": {
"total": costs.get("untagged", 0),
"pct_of_total": costs.get("untagged", 0) / sum(costs.values()) * 100,
"action": "INVESTIGATE — reduce to < 5%",
}
}
Anti-Patterns
| Anti-Pattern | Consequence | Fix |
|---|---|---|
| No mandatory tags | 40-60% of resources untagged | SCP/Policy enforcement at account level |
| Too many mandatory tags | Developers circumvent policies | 4-5 mandatory, rest recommended |
| Inconsistent naming | ”prod” vs “production” vs “Prod” | Enforce allowed values list |
| No tag auditing | Compliance drifts over time | Weekly tag compliance reports |
| Tag after creation | Resources created without tags, never fixed | Enforce at creation time via policy |
Tagging is the cheapest, highest-leverage FinOps practice. It costs nothing to implement, prevents nothing from running, and transforms a mystery bill into an actionable report.