You cannot optimise or budget what you cannot attribute. Allocation answers one question for every cost row: who owns this?
flowchart TB
ROW["Cost row"] --> A{"Dedicated account or project?"}
A -->|yes| OWN["Owner from account mapping"]
A -->|no| T{"Has owner tag?"}
T -->|yes| OWN2["Owner from tag"]
T -->|no| S["Shared or untagged pool"]
S --> SPLIT["Split by rule: even, proportional, fixed"]
%% step ROW: Every line in the billing data must end up with an owner.
%% step A: The strongest signal is structure: one account or project per team and environment.
%% step OWN: Account-to-team mapping allocates everything inside the account, even untaggable charges.
%% step T: Inside shared accounts, owner tags or labels decide.
%% step S: Shared platforms, support fees and untagged rows land in a pool.
%% step SPLIT: The pool is split by an agreed rule so 100% of spend is allocated.
Accounts first, tags second
- Account / subscription / project per team and environment is the most reliable allocation key: it covers resources that cannot be tagged and needs no discipline.
- Tags (AWS, Azure) and labels (GCP) add detail inside an account:
team,cost-center,env,app. - In AWS, user-defined tags appear in billing only after you activate them as cost allocation tags, and only from that point on.
A minimal tagging policy
| Key | Example values | Required? |
|---|---|---|
team |
checkout, search, platform | Yes |
env |
prod, staging, dev | Yes |
cost-center |
CC-4410 | Yes, for finance |
app |
web, api, worker | Recommended |
Enforce it where resources are created: Terraform modules with default_tags, AWS Organizations tag policies and SCPs, Azure Policy, GCP organisation policies, and CI checks. Then report the untagged percentage every week until it is small.
Shared costs
| Shared cost | Common split rule |
|---|---|
| Kubernetes cluster | By requested CPU and memory per namespace |
| Support plan, enterprise discounts | Proportional to each team's spend |
| Network hub, security tooling | Even split or fixed percentages |
Pick simple rules everyone understands; precision beyond that rarely changes decisions.
Traps: tag keys with different spellings (Team, team, owner_team) that split one owner into three; expecting tags to work backwards in time; and leaving shared costs unallocated, which makes every team look cheaper than it is.