Key takeaways
- A tag is not documentation. It is the join key that every cost report, budget and showback model depends on.
- Tags attach at usage time and never work backwards, so allocation coverage is earned month by month and can only be lost, never recovered.
- Five required tags that are enforced beat twenty recommended tags that are not.
- Enforcement belongs in infrastructure as code and admission control at creation time, not in a monthly spreadsheet chase.
- Between 10 and 25 percent of a typical bill can never carry a resource tag. Decide the allocation rule for that portion before anyone asks.
Every failed FinOps programme I have reviewed failed in the same place, and it was never the dashboard. It was the tag schema, agreed in a twenty minute meeting eighteen months earlier, written on a wiki page nobody has opened since, and applied to maybe two thirds of resources with three different spellings of the word production.
That is the whole problem in one sentence. Part 4 ended with a reconciliation table where 10.6 percent of spend had no owner attached. This part is about closing that gap, and about being honest that some of it will never close. Get this right and reporting, budgeting, showback, unit economics and anomaly detection all become tractable. Get it wrong and every later part of this series is built on sand.
What a tag has to do before it earns its place
A tag, called a label on Google Cloud, is a key and value pair attached to a resource. That definition is accurate and completely misleading, because it makes tagging sound like a filing exercise. In a FinOps context a tag does one specific job: it carries a dimension from the world of engineering into the world of money, so that a row in a billing export can be joined to something a human being is accountable for.
The FinOps Foundation puts this under the Allocation capability, which it describes as assigning and sharing cost and usage using accounts, tags, labels and other metadata to create accountability among teams and projects. Note the word accountability. A tag that nobody is accountable for is a tag that will rot, and a rotting tag is worse than no tag because it produces reports that look authoritative and are wrong.
So the test for any proposed tag is not is this useful information. It is: what decision changes when this value changes, and who do I telephone when it is missing. If a tag key cannot survive both halves of that question, it does not belong in the required set. It can live in an optional set, or better, it can live somewhere else entirely, because tags are a poor place to store data that has a real system of record.
There is a second job tags do that people underrate. They also determine what you can filter on when something goes wrong at three in the morning, and what an automation policy can safely act on. A schema designed only for the monthly report tends to be useless for both. Design it once for allocation, operations and automation together.
Five keys, not twenty
The single most common design error is an over specified schema. I have seen required tag lists with nineteen keys including things like project phase, ticket number and business justification. Every one of those was defensible in isolation and the combined effect was a schema with 40 percent compliance, because an engineer facing nineteen mandatory fields at three in the morning will find whichever path does not require them.
Five required keys is the number that has worked repeatedly for me. Owner, which identifies the team or individual accountable for the spend. Cost centre or business unit, which is the finance side of that same question and is deliberately separate because engineering ownership and financial ownership move independently. Environment, with a closed value list, because production and non production behave completely differently for both cost and risk. Application or service, which is the unit most unit economics work is eventually built on. And data classification or a similar compliance key, which is not a cost dimension at all but rides along because it is the one other thing you always need and will never get a second chance to apply.
Two rules make those five actually work. Values come from a closed list wherever possible, because free text guarantees you will end up allocating cost across prod, Prod, production and prd as four distinct teams. And keys must be case consistent, because tag keys are case sensitive on all three major clouds while some tooling silently normalises them, which produces a class of bug that takes a full day to find and thirty seconds to explain.
Three clouds, three tagging systems that only look alike
The vocabulary problem from Part 4 is at its worst here, because all three providers use the word tag and only two of them mean the same thing by it.
On AWS a tag exists on the resource but does not appear in your cost data until you explicitly activate that tag key as a cost allocation tag in the Billing and Cost Management console. Activation is a separate deliberate step, only the management account of an organisation can do it, and AWS documents that it can take up to 24 hours after a tag is first applied before the key even shows up in the activation list. AWS also states plainly that tags are not applied to resources that were created before the tags were created. There is one more trap worth knowing: if an account moves into a different organisation, previously activated cost allocation tags lose their active status and must be activated again by the new management account.
On Azure, not every resource emits its tags into the usage record, which historically left large holes in allocation. Microsoft solved this with tag inheritance, a Cost Management setting applied at the enterprise agreement billing account, the Microsoft customer agreement billing profile, or the subscription scope, which copies billing, resource group and subscription tags onto child resource usage records. Read that carefully, because the important qualifier is easy to miss: the inherited tags are applied to the usage records, not to the resources themselves, so Azure Policy and other services never see them. Microsoft states inherited tags appear on current month usage records within 24 hours of enabling the setting.
On Google Cloud the allocation construct is the label, and it is the one that needs the least ceremony: label information is forwarded to the billing system automatically, with no activation step, and appears in billing reports and the BigQuery export. Google Cloud also has a separate construct called a tag, which is a governance object used to conditionally allow or deny policies and is not a cost allocation mechanism at all. Confusing the two is the single most common Google Cloud tagging mistake I see, and it usually surfaces as a very confident engineer insisting the resources are tagged while the billing export shows nothing.
| Constraint | AWS | Azure | Google Cloud |
|---|---|---|---|
| Name of the construct | Cost allocation tag | Tag | Label |
| Max per resource | 50 user created tags on most services | 50 name and value pairs | 64 labels |
| Key length limit | 128 characters | 512 characters, 128 for storage accounts | 63 characters, lowercase only |
| Value length limit | 256 characters | 256 characters | 63 characters, may be empty |
| Extra step before billing sees it | Yes, activate each key in the Billing console | Optional, enable tag inheritance | No, forwarded automatically |
| Inheritance from a parent scope | No, tags do not inherit down an Organization | Yes, into usage records only, not onto resources | No, project is a grouping rather than an inherited label |
| Native enforcement mechanism | Organizations tag policies, with enforced_for | Azure Policy, deny and modify effects | Organization policy and custom constraints |
| Retroactive to past usage | No | Inheritance covers the current month only | No |
Limits verified against AWS Billing, Azure Resource Manager and Google Cloud Resource Manager documentation in July 2026. Per service exceptions exist on all three clouds, so check the specific service before assuming the general limit applies.
How to enforce tags without becoming the department everyone routes around
There are exactly three places you can enforce a tag, and they have very different costs. At creation time, by refusing to create an untagged resource. After creation, by detecting untagged resources and chasing an owner. Or never, by giving up and allocating by account or project instead. Most organisations attempt the middle option, which is the worst of the three, because detection produces a queue of work that grows faster than anyone clears it and generates no goodwill at all.
Enforce at creation. In practice that means the tag block is a required module input in your Terraform or Bicep or Pulumi module, so a plan without it fails in the pipeline where the engineer is already looking. Cloud native policy is the backstop for anything created outside that path, and it is a backstop rather than the primary control because policy denials appear at the console, hours after the intent, with an error message that rarely names the missing key.
On AWS the native control is an Organizations tag policy, which defines the permitted key spelling and value list, and optionally uses the enforced_for element to actually block noncompliant tagging operations on named resource types. That optional word matters more than anything else in this section. A tag policy without enforced_for reports compliance and prevents nothing, and I have walked into more than one organisation that believed it had enforcement running for a year when it had a compliance report running for a year.
Expected behaviour: a tagging operation that sets environment to Prod or Production on an EC2 instance is rejected, because tag values are case sensitive and only the three listed values are permitted. The common failure is omitting enforced_for entirely, which leaves you with a compliance report and no enforcement whatsoever. The second most common failure is enforcing on a service that was not in the list and assuming it was covered, so name each resource type deliberately and check the supported resource types before you rely on ALL_SUPPORTED.
Spend that will never carry a tag
Perfect tag coverage is not a realistic target, and chasing it is how good practitioners burn a year. A meaningful slice of every bill is structurally untaggable. Tax sits at the invoice level. Support and account level fees have no resource. Data transfer between availability zones has two ends and often no clean owner. Shared platform components such as a transit gateway, a central log sink or a Kubernetes control plane serve many teams by design. Commitment purchase fees, as covered in Part 4, exist before any team consumes anything.
So the target is not 100 percent tagged. The target is 100 percent allocated, which is a different and achievable thing: every currency unit on the invoice is attributed to somebody by either a tag or a written rule. Somewhere between 75 and 90 percent typically allocates directly by tag, and the remainder is allocated by an agreed split. The split rule itself matters less than the fact that it is written down, applied consistently, and reviewed on a schedule. Proportional to tagged spend is the default I reach for, because it needs no extra data and it is defensible in a room full of people who all think their team is being overcharged.
Where you can, replace the tag question with a boundary question. An account, subscription or project is itself an allocation dimension that never goes missing, never gets misspelled and cannot be edited off a resource by accident. If a workload is important enough to have a named owner, giving it its own account or project solves allocation permanently and solves several security questions at the same time. This is the recommendation people resist most and thank me for later.
| Unallocated charge | Amount, USD | Why it carries no tag | Rule I would apply |
|---|---|---|---|
| Legacy untagged compute | 3,410 | Created before enforcement landed | Remediate, this one is fixable |
| Inter zone data transfer | 1,180 | Two endpoints, often two owners | Proportional to tagged compute |
| Shared networking and log sink | 1,840 | Serves every team by design | Proportional to tagged spend |
| Support and account fees | 1,740 | No resource exists to tag | Central overhead, not distributed |
| Tax | 880 | Applied at the invoice level | Central overhead, not distributed |
| Unallocated total | 9,050 | 15.6 percent of a 58,000 invoice | 3,410 fixable, 5,640 by rule |
Illustrative, using the same 58,000 invoice from Part 4. The useful move is separating the fixable row from the rest, because only one line here rewards chasing.
My take
I no longer run tag compliance campaigns. They generate a lot of activity, a dashboard that goes green, and a coverage number that decays the moment attention moves elsewhere.
What works is boring and structural. Put the tag block in the module. Fail the pipeline. Publish one coverage number per team next to their spend number, in the same report, every month, with no commentary. Teams fix their own coverage when the two numbers sit side by side, because an untagged team looks like a team that does not know what it is running.
Reserve the enforcement conversation for new resource types and new accounts. Historic untagged resources are usually cheaper to leave alone until they are replaced anyway.
Publish coverage next to spend and enforce five keys in the pipeline
Here is the recommendation, and it fits in four actions. Agree five required keys with closed value lists this week, not nineteen. Activate every one of those keys in your billing configuration today, because activation is forward only and a day of delay is a day of history you cannot buy back. Put the tag block in the infrastructure as code module and fail the pipeline without it, using cloud native policy only as the backstop for resources created outside that path. Then publish, every month, one table with two columns per team: their spend and their allocation coverage.
Write down the split rule for the untaggable remainder at the same time, before anyone has an incentive to argue about it. A rule agreed in advance is administration. The same rule proposed after a team sees a number they dislike is a negotiation, and you will lose it.
Part 6 takes the allocation model built here and asks the organisational question that follows it, which is whether teams should simply see their costs or actually be charged for them. Showback and chargeback are not two settings on the same dial, and choosing wrongly sets a practice back a year. The full sequence, including Part 3 on the Framework and Part 4 on reading the bill, lives on the Cloud FinOps guide.
Before the next part, go and look up one number: what percentage of last month reconciles to a named owner. Write it on a wall. That figure is the ceiling on every allocation conversation you are going to have this year.
References
- Using user-defined cost allocation tags, AWS Billing User Guide
- Activating user-defined cost allocation tags, AWS Billing User Guide
- Tag policy syntax and examples, AWS Organizations
- Group and allocate costs using tag inheritance, Microsoft Cost Management
- Use tags to organize your Azure resources, Microsoft Learn
- Overview of labels, Google Cloud Resource Manager
- Allocation capability, FinOps Framework, FinOps Foundation
All monetary and percentage figures in this part are illustrative and chosen to show the shape of a real allocation problem. Provider limits and product names were verified in July 2026 and change over time.


DrJha