AWS Cost Allocation Tags: Best Practices for Financial Visibility
The goal: a tagging scheme that maps every dollar on the bill to a team, a product, or an environment that somebody owns. Without it, cost reduction is guesswork, because nobody can tell you who the spend belongs to.
An untagged AWS account tells you how much you are spending and nothing else. You cannot chargeback, you cannot set a per-team budget, and when the bill jumps you have no way to narrow the search. Tagging is the unglamorous prerequisite for every other piece of cost work.
Essential tag categories
Business tags
- CostCenter: finance department code
- Project: project identifier
- Team: owning team name
- BusinessUnit: department or division
Technical tags
- Environment: prod, staging, dev
- Application: application name
- Service: service identifier
- Version: application version
Implementing the strategy
Step 1: define the taxonomy
Write the schema down before anybody applies a tag. Case, allowed values, and who owns each key all need to be settled first, because retagging later is a migration.
Example tag structure
{
"CostCenter": "CC-1001",
"Project": "CustomerPortal",
"Team": "WebDev",
"Environment": "production",
"Application": "customer-portal",
"Service": "user-api",
"Owner": "john.doe@company.com",
"CreatedBy": "terraform",
"Backup": "daily",
"Compliance": "pci-dss"
}Step 2: enforce with policies
Voluntary tagging decays. Use AWS Organizations Service Control Policies to refuse resource creation without the mandatory keys:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"ec2:RunInstances",
"rds:CreateDBInstance",
"s3:CreateBucket"
],
"Resource": "*",
"Condition": {
"Null": {
"aws:RequestedRegion": "false",
"aws:RequestTag/CostCenter": "true",
"aws:RequestTag/Project": "true",
"aws:RequestTag/Environment": "true"
}
}
}
]
}Step 3: automate
Tag Policies and AWS Config cover drift. For everything created outside Terraform, an event-driven Lambda can apply the defaults:
# Lambda function to auto-tag resources
import boto3
import json
def lambda_handler(event, context):
ec2 = boto3.resource('ec2')
# Extract instance creation details
instance_id = event['detail']['instance-id']
instance = ec2.Instance(instance_id)
# Apply default tags
instance.create_tags(
Tags=[
{'Key': 'AutoTagged', 'Value': 'true'},
{'Key': 'CreatedBy', 'Value': 'lambda-auto-tagger'},
{'Key': 'CreatedDate', 'Value': event['time']}
]
)Cost reporting with tags
Activate each key as a cost allocation tag in the billing console first. Until you do, Cost Explorer will not group by it, and the data does not backfill:
import boto3
from datetime import datetime, timedelta
def get_cost_by_tag(tag_key, start_date, end_date):
ce = boto3.client('ce')
response = ce.get_cost_and_usage(
TimePeriod={
'Start': start_date.strftime('%Y-%m-%d'),
'End': end_date.strftime('%Y-%m-%d')
},
Granularity='MONTHLY',
Metrics=['UnblendedCost'],
GroupBy=[
{
'Type': 'TAG',
'Key': tag_key
}
]
)
return responseCommon pitfalls
Inconsistent tag values
Problem: "Prod", "Production", and "PROD" become three separate cost buckets.
Fix: tag policies that pin the allowed values and the casing.
Too many tags
Problem: a twenty key schema nobody fills in correctly is worse than a five key one everybody does.
Fix: start with 5 to 7 keys and add more only when a specific question needs them.
Legacy resources
Problem: everything created before the policy has no tags at all.
Fix: bulk apply with the Resource Groups Tagging API, working down from the largest line items.
Monitoring tag compliance
An AWS Config rule reports which resources are missing required tags, so compliance becomes a number you can track rather than an assumption:
# AWS Config rule for required tags
aws configservice put-config-rule \
--config-rule '{
"ConfigRuleName": "required-tags",
"Source": {
"Owner": "AWS",
"SourceIdentifier": "REQUIRED_TAGS"
},
"InputParameters": "{\"tag1Key\":\"CostCenter\",\"tag2Key\":\"Project\",\"tag3Key\":\"Environment\"}"
}'Untagged spend is one of the first things we flag in our AWS cost audit, which comes at a fixed price.
Where to start
Do not try to tag everything at once. Sort the bill by line item, tag the top ten cost drivers, and put an SCP in front of new resources so the gap stops growing. That gets you a usable per-team view in a week, and the long tail can follow.