Cloud & Infrastructure Bug Report

Tags on every AWS resource but Cost Explorer shows No tag key

We spent a quarter tagging every resource with team and service, then grouped Cost Explorer by tag and saw 92 percent under No tag key. User-defined tags must be activated as cost allocation tags, they apply from activation onward, and some spend cannot be tagged at all.

Ryan Pham Ryan Pham @ryan_bugs · July 16, 2025 · 6 min read · 5 Views
Banner: AWS resources tagged but costs still show no tag key in Cost Explorer

Our FinOps project had one goal for Q2: cost per team and per service. Engineering spent weeks adding team and service tags through Terraform default tags, Kubernetes node labels propagated to EC2, and a cleanup of manually created resources. A tag compliance report showed 96 percent of taggable resources tagged.

Then we opened Cost Explorer, grouped by tag team, and saw:

Tag: team           Cost (USD, last 30 days)
No tag key               212,480
search                     9,120
payments                   6,870
...

92 percent of spend under "No tag key".

Reproducing it

The tag key team did not even appear in the tag picker for most of the period. In the Billing console, under Cost allocation tags, the team key was listed under user-defined tags with status Inactive.

What we ruled out

  • Tagging gaps. Resource Groups Tag Editor showed tags present on the resources.
  • Wrong account. We were looking at the management account, where cost allocation tags are activated for the organisation.
  • Cost Explorer caching. Data was refreshed daily, and other dimensions were current.

Root cause

Three things combined. First, user-defined tags must be activated as cost allocation tags in the management account before they appear in billing data; we had never activated team or service. Second, activation is not retroactive by default: costs from before activation show no tag even if the resource was tagged. Third, a meaningful share of spend cannot carry resource tags at all: support plans, some data transfer, tax, Savings Plans fees and certain marketplace charges.

What is happening under the hood

AWS billing data is produced from usage records. A resource tag becomes a column in billing data only when its key is activated as a cost allocation tag. After activation, it can take up to 24 hours for the key to appear in Cost Explorer and the Cost and Usage Report, and tagging data applies to usage from then on. AWS offers a backfill option for cost allocation tags so you can request tag data for earlier months, within a limited lookback; check the Billing console for the current limits.

Tag keys are case-sensitive. team, Team and TEAM are three different cost allocation tags. We found all three in use.

Some costs are never tied to a resource: account-level fees, support, refunds and credits, some networking charges, and taxes. These always show "No tag key" and need a separate allocation rule.

Environment

Component Version / value
Organisation AWS Organizations, 23 member accounts
Tagging Terraform default_tags, Kubernetes node tags, Tag Editor cleanup
Billing Cost Explorer, Cost and Usage Report 2.0 to S3
Keys in use team, Team, service, Service, owner

Minimal reproduction

Tag an EC2 instance with team=search, wait a day, group Cost Explorer by tag team. If the key is not activated as a cost allocation tag, the instance's cost is under "No tag key".

The fix

1. Activate the keys in the management account, under Billing, Cost allocation tags. We activated team, service and environment. The CLI works too:

aws ce update-cost-allocation-tags-status \
  --cost-allocation-tags-status TagKey=team,Status=Active TagKey=service,Status=Active TagKey=environment,Status=Active

2. Request a backfill for the months the tags existed but were not active, so Q2 reports had tag data.

3. Normalise casing. We picked lowercase keys and enforced them with an AWS Organizations tag policy:

{
  "tags": {
    "team": {
      "tag_key": {"@@assign": "team"},
      "enforced_for": {"@@assign": ["ec2:instance", "ec2:volume", "rds:db", "s3:bucket"]}
    }
  }
}

Existing Team tags were migrated with a script over Resource Groups Tagging API, since tag keys cannot be renamed in place.

4. Cost categories for what tags cannot cover. AWS Cost Categories map costs to teams using rules on accounts, services and tags. Untaggable costs, such as support and shared data transfer, are split proportionally across teams with a split charge rule. Accounts dedicated to one team map entirely to that team, which covers anything untagged in those accounts.

Alternatives and trade-offs

  • Account per team as the primary allocation dimension. Very clean for allocation, more overhead in account management. We use a mix: dedicated accounts where possible, tags in shared accounts.
  • Allocate only from the Cost and Usage Report in your own data warehouse. Maximum flexibility; you still need the tags activated to see them in the report.

How to test the fix

Two days after activation, Cost Explorer grouped by team for the last 48 hours showed 71 percent of spend tagged. After the cost category rules, 100 percent of spend mapped to a team or the explicit shared bucket. After the backfill completed, Q2 showed tag data from the start of the quarter.

Confirming in production

  • Monthly showback reports per team now cover all spend, with 4 percent in a visible "shared" category that is split by rule.
  • Untagged taggable resources are under 2 percent, down from a long tail of manual resources.

Regression guard

  • Tag policies enforce keys and allowed values for key resource types.
  • Terraform default_tags in every provider block, checked by a CI policy.
  • A monthly check lists any new user-defined tag key with cost data that is not activated.

Security implications

Tags are visible to anyone with read access to resources and appear in billing exports, so they must not contain secrets or personal data. We found one tag with an engineer's personal email as owner; owners are now team names. Tag-based IAM conditions (ABAC) also depend on consistent keys, so the casing cleanup reduced a class of authorisation mistakes too.

Prevention checklist

  • Activate cost allocation tags in the management account as soon as you define keys.
  • Request a backfill if tags existed before activation.
  • Choose one casing and enforce it with tag policies.
  • Use cost categories and split charges for untaggable and shared costs.
  • Never put secrets or personal data in tags.

References

Add a label

#aws #finops #cost-allocation #tagging #cost-explorer
Written by
Ryan Pham @ryan_bugs

I build and run the platforms other engineers ship on: CI/CD pipelines, Kubernetes clusters, GPU inference services, LLM features in production, and the cloud bills that come with all of it. I have also spent years writing and operating automated trading systems, where a rounding bug or a missed websocket message is not a log line but a position you did not intend to hold. Each post here starts from a real failure: the alert, the exact error, what we ruled out, the root cause, and how we proved the fix. Same path every time: Investigate, Explain, Fix, Verify. No hype, no price predictions, just engineering.

Advertisement

Comments

0

No comments yet. Be the first to comment!

Sign In to post a comment.