Outcome
By the end of this lesson, you will be able to trace any dollar of cloud spend back to a team using tags, and identify the four tags every cloud estate needs as the minimum viable tag set.
| Tier | Operator |
| JTBD | ”Show me which team is spending the money.” |
| Personas | All five |
| Prerequisites | L1, L2 |
| Time | 10 minutes |
| Bloom verb | Trace (Apply) |
1. Concept
A cloud bill without tags is a pile of money with nobody’s name on it.
A tag is a label you attach to a resource: a key and a value, such as team = billing. The provider copies those labels onto every charge that resource generates. Tag well and any amount on the bill can be traced to an owner with one query. Tag badly and the bill becomes something teams argue about rather than act on.
Google calls them labels; AWS and Azure call them tags. The mechanics are the same, and so is the minimum set worth having.
The minimum viable tag set (MVT)
Four tags. Every resource carries them. The values are governed.
TAG KEY WHO USES IT EXAMPLE VALUES────────────────────────────────────────────────────────────environment Finance, Eng, Sec dev | test | stage | prodteam Finance, Eng billing | identity | growth | datacost_center Finance, Procurement eng-platform | eng-product | gtm | corpowner Sec, Ops an email address or group aliasMore than these four is optional. Fewer is a gap you will feel within a month. Together they answer the four questions that actually get asked:
- Which environment is spending the most? (group by environment)
- Which team owns this resource? (look at team)
- What cost center does this charge against? (look at cost_center)
- Who do we email when this misbehaves? (look at owner)
The cost-attribution problem
Without tags, the only thing you can attribute by is the cloud account. One account, one team. That holds at small scale. It breaks the first time a team uses a shared services account, a sandbox is passed between teams, or two teams co-own an application.
With tags, attribution comes from the resource itself, so a shared database can be split between the teams using it. Anything untagged collects in a bucket usually labelled Unattributed: visible, but unowned.
That bucket is worth watching as a number in its own right. It should be shrinking. If it is not, tagging is a policy nobody is enforcing.
The tag-drift problem
Tags decay unless somebody governs them. Three forces do the damage.
- Manual tagging. Somebody creates a resource in the console and skips the tags. The resource exists, the bill is running, and the owner field is empty.
- Reorganisations. A team called
growthbecomesmonetization. New resources carry the new name, old ones keep the old one, and one team’s spending now appears as two. - Case and spelling. A policy says
environmentmust be lowercase, but existing resources carryEnvironment=Production. Reports treat “Production” and “prod” as two different places.
The fix is tag policy as code, enforced at provision time (Terraform / CDK / Pulumi pre-commit hook) and audited continuously (the tagging service flags drift).
A note on hierarchies
Tags are flat. There is no built-in parent and child, no team.subteam. If you need hierarchy you either add a second key, team plus subteam, or encode it in the value, team=identity-auth and team=identity-mfa.
Either works. Mixing the two does not, and it is very hard to unpick a year later.
2. Demo
The same query, three providers, attributing yesterday’s compute spend to teams:
AWS:
-- CUR querySELECT resource_tags_user_team AS team, SUM(line_item_unblended_cost) AS spendFROM cur.consolidated_2026_05WHERE line_item_product_code = 'AmazonEC2' AND DATE(line_item_usage_start_date) = DATE '2026-05-19'GROUP BY resource_tags_user_teamORDER BY spend DESC;GCP:
-- BigQuery billing exportSELECT labels.value AS team, SUM(cost) AS spendFROM `billing_export.gcp_billing_export_v1_*`, UNNEST(labels) AS labelsWHERE labels.key = 'team' AND service.description = 'Compute Engine' AND DATE(usage_start_time) = '2026-05-19'GROUP BY teamORDER BY spend DESC;Azure:
az consumption usage list \ --start-date 2026-05-19 \ --end-date 2026-05-20 \ --query "[?contains(meterCategory, 'Virtual Machines')].{team:tags.team, cost:pretaxCost}" \ -o json | jq 'group_by(.team) | map({team:.[0].team, cost: (map(.cost | tonumber) | add)})'Sample output:
team spend─────────────────identity $1,247.30growth $ 893.10data $ 612.40(null) $ 211.80 ← Unattributed. This bucket should trend to zero.3. Hands-on (8 min)
- Pick the four tag keys:
environment,team,cost_center,owner. - Query your own bill for last month. Group by
team(or label-equivalent). - Note the Unattributed bucket. What percent of total spend has no team tag?
- Pull a list of the top 20 untagged resources (sort by spend descending).
- For the top 5 untagged resources, find the actual owner. Use the cloud console, Slack, or a CMDB.
- If the owner can be determined, apply the four MVT tags through your IaC or console. If the owner cannot be determined, the resource is a candidate for the orphan list: see lesson 5.
Time-bounded version: do this for the top 3 untagged resources only. Eight minutes, not eight hours.
4. Knowledge check
Q1
A FinOps Analyst reports: “We can’t attribute 18% of our cloud bill.” The most accurate first response is:
A. The cloud provider is hiding cost data
B. The tag coverage is incomplete
C. Tags don’t work at scale; use account boundaries
D. Buy a more expensive FinOps tool
Show answer
Correct: B. Find the untagged resources by spend, then assign owners. 18% Unattributed is high but not unusual. The fix is mechanical: list the untagged resources by spend, find the owners, apply the four MVT tags, and re-run the report.
Q2
A reorg renames “Growth” to “Monetization.” The team field on existing resources is not updated. What is the immediate cost-reporting consequence?
A. The cost of the old Growth team continues to show up under the old name, while new resources show under the new name
B. No consequence
C. Tags become invalid
D. The bill double-counts the spend, since both the old and the new tag value are now present on the resource
Show answer
Correct: A. The combined team’s spend appears split. Tag values are not retroactive. The old team=growth resources carry that value until updated. Reports will show two separate buckets that are the same team. The fix is a bulk tag update on existing resources at the time of the reorg.
Q3
A new tag policy requires environment to be lowercase. The CI policy is added today. What needs to happen?
A. Nothing; new resources comply
B. Run a one-time bulk update of existing resources (rename Environment to environment, normalize values to lowercase)
C. Wait three months for all of the old resources to be replaced naturally through the normal deployment cycle
D. Just live with the inconsistency
Show answer
Correct: B. Then the policy holds. New policies on new resources do not retroactively fix old resources. A one-time reconciliation is required at the moment a policy changes.
5. Apply
ZopNight’s Reports page exposes the cost-attribution surface in three ways:
- Reports → Teams splits spend by the
teamtag (and shared services by share count). The Unattributed bucket appears as its own row. - Reports → Tags lets any tag key (cloud-native or an accepted Smart Tag) drive the breakdown. Stacked trend chart, expandable rows for provider and resource-type breakdowns.
- Tag Coverage Widget on the dashboard shows tagged-vs-untagged as a donut. The target is “Untagged ≤ 5%.”
Smart Tags closes the gap from the other side. You write a tagging policy that enforces a tag key and derives its value from the resource’s own fields (provider, region, type, instance_type, name), and the derived value counts toward attribution inside ZopNight once accepted, without anything being written to your cloud account. A derived value that already matches the resource’s live cloud tag is accepted automatically. Accepted tags carry dimension_source=auto so they stay distinguishable from cloud-native ones. See 8.
Open ZopNight Reports → Tags (deep link)
Related lessons
- L5: The ten cost mistakes that show up on every bill (next)
- T2.M2.8: Smart Tags
- T3.M3.5: Showback design
- T5.M5.1: Tagging strategy that survives reorgs
Glossary terms touched
Tag · Label · Unattributed · Tag coverage · Minimum viable tag set