Outcome
By the end of this lesson, you will be able to write a tagging policy from the resource fields, existing tags and literal values, judge whether a derived key is worth attributing on, and avoid the policies that look complete but attribute nothing.
| Prerequisites | M2.8.L1 |
| Time | 9 minutes |
1. Concept
A tagging policy is small by design: one tag key, a selector for which resources it covers, and a rule for deriving its value. The editor is catalog-driven, at Governance → Policies → Tagging, and the value sources are the ones from L1.
provider aws | gcp | azureregion us-east-1, europe-west1, eastus, ...type ec2, rds, gke-cluster, s3, ...instance_type m5.large, db.r6g.xlarge, ...name the resource's own nametag.<key> a tag the resource already carriesliteral text a fixed value typed into the policy
VALUE SHAPES compose (join parts), template, lookup tableSELECTOR match on the fields above, plus status and cloud account: equals, contains, regex, in listThat constraint is the design. A policy cannot call out to a CMDB, read an activity log, or query an external owner directory, so it cannot be quietly wrong in a way you would not notice. Everything it produces is inspectable from the resource row and the policy itself.
The one question that decides whether a policy is worth writing
Does the derived value identify a thing someone can be accountable for?
GOOD WHY─────────────────────────────────────────────────────────────name -> team prefix Names usually encode ownership in an estate with any naming convention at allprovider + region Useful when teams ARE split by region, useless when they are nottype Good for workload-class reporting; never for chargeback
BAD WHY─────────────────────────────────────────────────────────────provider alone Produces 1-3 values across the whole estate. Attributes nothing.instance_type A shape, not an owner. Nobody is accountable for "m5.large".region, in a single-region org One value. Same problem as provider alone.The failure mode is specific and worth naming: a policy that derives cleanly across 100% of the estate and produces three distinct values. Coverage goes green, the Unattributed bucket empties, and the report is now less honest than the empty one it replaced, because it looks resolved.
Cardinality is the test
Before accepting anything from a new policy, look at how many distinct values it produced against how many owners you actually have.
DISTINCT VALUES vs REAL OWNERS ~1 value attributes nothing. Delete the policy. Far fewer than owners partial. Useful only if the axis is genuinely how spend is owned. Roughly one per owner this is what you want. Far more than owners the key is too granular to report on. Usually a policy that composes the full name, instance suffix and all.Designing a name-derived policy
Name is the most useful of the resource fields, because in most estates the name is the only place ownership got written down.
TYPICAL NAMING HOW A POLICY GETS THE TEAM─────────────────────────────────────────────────────────────payments-api-prod-03 selector: name regex ^payments- value: literal "payments"platform-eks-staging selector: name regex ^platform- value: literal "platform"db-analytics-01 selector: name contains analytics value: literal "analytics"i-0a3f9c2b1d nothing usable. Cloud-generated names carry no information.
There is no "take the leading segment" transform. A per-teamvalue comes from one policy per team on the same key: a nameselector plus a literal value.
BEFORE WRITING ONE: sample 50 resource names. If more than a few are cloud-generated ids, a name policy will produce a long tail of junk values that you then have to leave pending.Multiple policies coexist
Policies on different keys stack, so a resource can carry several derived tags. Several policies can also share one key (one per team, for example). When more than one matches the same resource, the most specific scope wins (cloud account over organisation), then priority, then the earliest created.
POLICY A key: cost-allocation from: provider + regionPOLICY B key: workload-class from: typePOLICY C key: team from: name selectors + literal values
A resource can be pending on B while accepted on A and C.Accept and revoke act on the resources you select and thekeys you name.That is also the fix for the analytics estate from L1: when region is the wrong axis for one part of the estate, you do not weaken the region policy. You add a second policy on a better axis and accept it where it fits.
What a policy cannot do
Worth stating plainly, because these are the four requests that come up:
"Derive team from the CloudTrail creator" No. Ownership detection reads activity logs and is a separate feature; it is not available to a policy.
"Derive environment from whether the resource has a schedule" No. Policies see resource fields, not ZopNight state.
"Only apply to resources over $100/month" No. There is no cost predicate in the policy language.
"Use a regex with a fallback chain" Check the editor's current catalog before promising this to anyone. The catalog is the source of truth for what transformations are available, and it changes per release.2. Demo
Two policies written against the same estate, one useful and one not:
ESTATE: 2,259 resources, 3 clouds, 6 regions, 11 owning teams
POLICY 1 (written first) key: cloud-provider derived from: provider RESULT: derived on 2,259 (100% coverage) distinct values: 3 VERDICT: deleted. 100% coverage, zero attribution. It would have taken Unattributed to 0% while telling the FinOps lead nothing they did not already know from the provider filter.
POLICY 2 (the replacement) key: team derived from: one policy per name prefix found in a sample (name regex selector + literal) RESULT: derived on 1,904 (84% coverage) distinct values: 14 11 match known teams 1,781 resources 3 are junk: prefixes that were 123 resources really generated names (i-0a3f, vol-88c1, eksctl-) ACTION: accepted the 11 real teams. left the 3 junk values pending, permanently. 355 resources produced no value at all (cloud-generated names). VERDICT: kept. 79% of spend now attributed to a named team; the remaining 21% is visibly unattributed, which is the honest state.
THE COMPARISON THAT MATTERS Policy 1: 100% coverage, 3 values, 0 real attribution Policy 2: 84% coverage, 14 values, 11 real ownersPolicy 1 is the trap. It scores better on every dashboard metric and is worth nothing.
3. Hands-on (6 min)
Design one policy for your own estate, on paper before touching the editor:
1. Sample 50 resource names from Resources. How many carry a human-chosen prefix rather than a cloud- generated id? ___/50 Under about 30? Skip the name axis entirely.
2. How many owning teams does your org actually have? (The number you would put on a chargeback report.) ______
3. Pick your axis and predict the cardinality: axis: ______________ predicted distinct values: ____ Within 2x of your answer to 2? Y / N If N, this policy will not attribute. Pick again.
4. Write the key name. It has to survive a reorg, so avoid anything containing a current team name. key: ________________________________________
5. Create it, refresh, and compare actual distinct values to your prediction: predicted ___ actual ___ A large gap means you do not know your naming convention as well as you thought. Look at the outliers before accepting anything.4. Knowledge check
Q1
A policy derives cloud-provider from provider and reaches 100% of the estate with 3 distinct values. Tag coverage goes green. The right action:
A. Accept it. 100% coverage is the goal
B. Leave it pending forever
C. Delete it
D. Accept it and add a second policy
Show answer
Correct: C. Coverage measures whether a value exists, not whether it attributes anything. Three values across the whole estate identify nobody, and accepting it would empty the Unattributed bucket while making the report less honest than the gap it replaced. This is the central trap of derived tagging: the policies that are easiest to write score best on the coverage metric and attribute the least. Judge a policy by distinct values against real owners, never by coverage percentage.
Q2
Your estate has 11 owning teams. A name-derived policy produces 14 distinct values: 11 matching teams and 3 junk values from cloud-generated names. The best handling:
A. Accept all 14; the junk values are harmless
B. Delete the policy outright, because it is not 100% accurate
C. Rename the resources first
D. Accept the 11 real values and leave the 3 junk values pending
Show answer
Correct: D. Accept and revoke act on the resources and keys you select, so partial acceptance is the intended workflow, and the resources behind the junk values stay visibly unattributed rather than being attributed to a meaningless bucket. Partial acceptance is normal and correct. The 3 junk values staying pending is a feature: those resources show up as Unattributed, which is a true statement about them, and it points at a naming problem worth fixing at the source.
Q3
A FinOps lead asks for a policy that tags only resources costing more than $100 per month. The accurate response:
A. Write it with a cost predicate in the policy editor
B. Possible, but only for AWS
C. Not possible
D. Possible via the auto-tagger’s confidence threshold
Show answer
Correct: C. A policy derives its value from the resource’s fields, its existing tags, and literal text or lookup tables in the policy. There is no cost predicate, no metric input and no ZopNight state available to it, so any filtering by spend has to happen when reading the report, not when deriving the tag. D references the removed heuristic auto-tagger, which had confidence tiers; Smart Tags has neither confidence nor cost predicates. The constraint is deliberate: everything a policy produces is inspectable from the resource row itself.
5. Apply
Write your policy at Governance → Policies → Tagging, then check its cardinality on Smart Tags before accepting anything. Distinct values against real owners is the only measure that tells you whether the policy earns its place.
Related lessons
- L1: What Smart Tags derive
- L3: Accept, revoke, apply to cloud (next)
- T3.M3.1.L2: The minimum viable tag set
- T3.M3.1.L5: Reorg-proof tagging
Glossary terms touched
Tagging policy · Derived tag · Tag taxonomy