Cost Tagging and Allocation
I once sat in a budget meeting where engineering and finance argued for forty minutes about a $22,000 "unallocated" line item. It was three untagged RDS instances and a NAT gateway nobody owned. Cost tagging isn't bureaucracy—it's the difference between "the cloud is expensive" and "Team Payments grew 18% because they doubled Aurora IOPS."
Design a tag schema before enforcing it
Start with five mandatory tags every billable resource must carry:
| Tag key | Example values | Purpose |
|---|---|---|
Environment |
prod, staging, dev | Separate prod spend from sandbox waste |
Team |
payments, platform | Chargeback owner |
Service |
checkout-api, auth | Application-level attribution |
CostCenter |
CC-1042 | Finance GL mapping |
ManagedBy |
terraform, manual | Audit drift |
Use lowercase keys consistently (team, not Team and TEAM). Publish allowed values in a Confluence page or internal repo—free-form tags become unusable in reports within months.
Optional but valuable: Project for time-bound work, Compliance for PCI/HIPAA boundaries, ExpiresOn for temporary resources.
Activate tags in the billing console
Creating tags on resources is step one. Activation is step two—and the step most teams skip.
AWS: Billing → Cost Allocation Tags → activate user-defined tags. Wait 24 hours for data to populate Cost Explorer.
GCP: Labels propagate automatically; use BigQuery billing export for analysis.
Azure: Tags sync to Cost Management; configure cost allocation rules for subscriptions.
Without activation, your FinOps dashboard shows 30–50% spend as "No tag" even when engineers tagged diligently.
Enforce with policy, not email
Tag enforcement via quarterly reminders fails. Automate:
AWS Service Control Policy (org level):
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyUntaggedEC2",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"Null": {
"aws:RequestTag/team": "true",
"aws:RequestTag/environment": "true",
"aws:RequestTag/service": "true"
}
}
}]
}
Terraform — use default_tags on the AWS provider so every resource inherits baseline tags:
provider "aws" {
default_tags {
tags = {
ManagedBy = "terraform"
Environment = var.environment
Team = var.team
}
}
}
Tag compliance scanners — AWS Config rules (required-tags), Steampipe, or Cloud Custodian flag violations daily. Auto-remediate dev accounts; alert for prod.
Cost Categories for shared services
Some costs don't belong to one team. NAT gateways, AWS Organizations, GuardDuty, and centralized CloudWatch log archives are shared. AWS Cost Categories let you split them:
Shared NAT Gateway
├── 40% → Team A (by VPC flow log bytes)
├── 35% → Team B
└── 25% → Team C
Define categories in the billing console or via API, then map untagged or platform-tagged resources into logical buckets. Export to CUR and join with custom allocation weights in SQL:
SELECT
resource_tags_user_team AS team,
SUM(line_item_unblended_cost) AS direct_cost
FROM cur
WHERE bill_period = '2024-08'
GROUP BY 1
UNION ALL
SELECT team, shared_cost * allocation_pct
FROM shared_cost_allocations;
Publish the allocation methodology. Engineers accept chargebacks they understand; they fight ones that feel arbitrary.
Chargeback vs. showback
Showback — report costs to teams without internal invoicing. Good for building awareness.
Chargeback — deduct from team budgets. Drives behavior but requires accurate allocation.
Start with monthly showback dashboards (Grafana, Vantage, CloudZero). Graduate to chargeback once untagged spend drops below 5% and shared-cost rules are stable.
Include unit economics: cost per request, cost per active user, cost per GB processed. A team whose absolute spend rose 10% but cost-per-request fell 20% is optimizing; raw totals hide that.
Remediating historical mess
Existing environments won't retag themselves. Prioritize:
- Top 20 resources by spend (Cost Explorer → Group by Resource).
- Production first—biggest dollars and political visibility.
- Automate tag inheritance (ASG tags flow to instances; EKS tags to node groups).
Run a tagging sprint with named owners per service. Block new launches without tags while backfilling old ones over 4–6 weeks.
Metrics that prove tagging works
Track monthly:
- Untagged spend % — target < 5%.
- Tag compliance rate — % resources passing Config rules.
- Time to allocate new service — days from first deploy to full tag coverage.
- Finance reconciliation gap — sum of team chargebacks vs. total bill (should match within 1–2%).
When these metrics hold, cost conversations shift from allocation arguments to optimization decisions.
Tag governance at scale
Large orgs assign tag policy owners per tag key—Finance owns CostCenter values, Platform owns Environment, product managers own Service catalogs. Changes go through pull request review on a tags.yaml source-of-truth file that Terraform and SCPs reference. This prevents "payments" vs "Payments" vs "team-payments" fragmentation that breaks dashboards.
Run weekly Steampipe or CloudQuery reports joining tag compliance with spend. Teams above 10% untagged spend get automatic Slack alerts with top untagged resources listed—specificity drives action faster than generic finance emails.
Multi-cloud tagging needs harmonized keys—use Team and Environment consistently across AWS, GCP, and Azure even if underlying label mechanisms differ. FinOps tools like Vantage normalize tags for unified chargeback. Finance reconciliation monthly: sum of allocated team totals must equal invoice within documented shared-cost adjustment percentage.
Production teams should treat this guidance as living documentation: revisit assumptions after major platform upgrades, measure outcomes with real metrics rather than checklist compliance, and pair written standards with automated checks in CI. The patterns here reflect what held up in shipped apps—not theoretical perfection. Adapt thresholds, timeouts, and tooling to your stack, but keep the underlying principles: explicit configuration, testable behavior, and failure modes users can understand.
Resources
- AWS Cost Allocation Tags
- AWS Cost Categories
- GCP Label Best Practices
- Azure Tagging Strategy
- FinOps Foundation: Allocation
Frequently asked questions
What tags are required for cloud cost allocation?
At minimum: Environment (prod/staging/dev), Team or Owner, Service or Application, and CostCenter or BusinessUnit. Add Project for ephemeral initiatives and ManagedBy for Terraform versus manual resources. Consistent naming—lowercase keys, agreed values—matters more than tag count.
Why doesn't my AWS tag show up in Cost Explorer?
User-defined tags must be activated as Cost Allocation Tags in the Billing console before they appear in reports. Resources tagged retroactively only report costs from activation forward, not historical spend. Some services (CloudFront, Support) need Cost Categories for allocation instead of resource tags.
How do you allocate shared infrastructure costs?
Split shared costs—NAT gateways, centralized logging, security tooling—using proportional rules: by compute hours, request count, or headcount per team. AWS Cost Categories and custom CUR SQL implement this. Document the formula so teams understand their bill, not just receive it.
Hiring a senior Android / Flutter engineer?
I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.
Get in touch →