A company tried to track cloud costs using tags. They defined 200 tags: project names, cost centres, environments, owners, business units. Every resource was supposed to be tagged. Compliance never broke 40%. Chargeback accuracy sat at 70-80%. Finance spent 20 hours a month reconciling discrepancies.
Six weeks later, they scrapped the tags. Chargeback accuracy hit 92-96%. The fix was simpler than the problem: a four-field lookup table maintained by FinOps, not enforced through tagging policy.
Why Tagging Fails
Cloud tagging sounds logical. Apply metadata to every resource, then aggregate costs by tag. In practice, it collapses under three pressures.
First: tag entropy. Teams use different formats. One writes "prod", another writes "production", a third writes "prd". The taxonomy says "environment: production" but nobody reads the taxonomy. Tag values drift over time. A project name changes but tags don't get updated. Six months later, half your resources have stale metadata.
Second: coverage gaps. Automated deployments skip tags. Developers forget tags when they're moving fast. Legacy resources predate the tagging policy. Emergency fixes bypass the checklist. You end up with 40% compliance if you're lucky, 20% if you're honest.
Third: enforcement is expensive. You can write policies that block untagged resources. Now developers can't deploy without filling out metadata. Velocity drops. Exceptions accumulate. The policy gets relaxed, then ignored, then forgotten. Enforcement fails because it fights human behaviour instead of working with it.
The Four-Field Alternative
The replacement schema has four fields: cost_center, service, env, owner_email. That's it. No project names, no business units, no departmental hierarchies. Just four pieces of information maintained in a single lookup table owned by FinOps.
The table lives in a database, not in cloud tags. Each row maps account IDs or service identifiers to chargeback metadata. When finance needs cost allocation, they join cloud billing data against this table. The lookup absorbs tag variance - if three teams write environment names differently, the table translates them all to canonical values.
This inverts the maintenance model. Instead of 200 engineers maintaining tags on thousands of resources, one FinOps team maintains a table with hundreds of rows. Updates happen in one place. Corrections propagate instantly. Historical data gets retroactively fixed by updating the lookup, not retagging old resources.
How It Works In Practice
A developer spins up a database in the DataTeam account. They don't tag it. They don't think about chargeback. They just build.
At month-end, finance pulls billing data. The database cost appears under account ID 123456789. Finance queries the lookup table: account 123456789 maps to cost_center "Engineering", service "DataPipeline", env "prod", owner "[email protected]". The cost gets allocated correctly without the developer doing anything.
If the allocation is wrong - maybe that database should charge to Marketing, not Engineering - FinOps updates one row in the table. Next month's report reflects the correction. Last month's report can be regenerated with the fix applied retroactively. No retagging. No deployment. Just a database update.
What Changed After Six Weeks
Chargeback accuracy rose from 70-80% to 92-96%. The remaining 4-8% are legitimate ambiguities - shared infrastructure, cross-team services, costs that genuinely belong to multiple budgets. Those require human judgment. The table doesn't solve them, but it surfaces them cleanly instead of hiding them in tag noise.
Finance stopped spending 20 hours a month on reconciliation. Most corrections became 30-second table updates. Complex cases still require investigation, but routine errors disappeared. The FinOps team could focus on optimisation instead of data cleanup.
Developer friction dropped to near zero. Nobody blocks deployments over missing tags. Nobody fills out metadata forms. The system works silently. Costs get allocated. Teams get invoiced. Nobody notices the mechanism, which is exactly how infrastructure should work.
The Design Principle
The insight here isn't technical - it's organisational. Policy should live where it's maintained, not where it's enforced. Enforcing policy at deployment time puts the burden on developers who have incomplete information and urgent deadlines. Maintaining policy centrally puts the burden on the team with complete information and the mandate to keep it accurate.
This applies beyond cost allocation. Security policies, compliance rules, operational standards - anything that requires organisation-wide consistency. The traditional approach enforces rules at the edge: every engineer must follow the checklist. The alternative centralises the rule and distributes only the mechanism.
Tags-for-chargeback is edge enforcement: tag every resource correctly or costs won't allocate. Lookup-table-chargeback is centralised rule with distributed mechanism: FinOps maintains the mapping, billing automation applies it. The developer doesn't see it. The finance team controls it. Nobody fights over incomplete metadata at 2am during an outage.
When This Doesn't Work
This approach assumes costs map to accounts or services more naturally than to individual resources. If you need per-resource allocation - tracking costs for specific customer workloads, for example - you still need tags. The lookup table handles 80-90% of cases. The remaining 10-20% need finer granularity.
But even then, the principle holds: minimise the number of tags developers must maintain. Use the lookup table for organisational metadata. Use tags only for information that genuinely varies per resource. A hybrid approach works: three maintained tags plus a lookup table, not 200 aspirational tags.
The lesson from those six weeks: simpler systems maintained by fewer people beat comprehensive systems maintained by everyone. Not because people are lazy - because maintenance is work, and work needs ownership. Distributed ownership of 200 tags means no ownership. Centralised ownership of four fields means someone fixes it when it breaks.