Untagged Spend Is a Budget Risk, Not Just a Policy Violation
Every FinOps team knows the tagging mandate. Tag every resource with cost center, team, environment, and project. The mandate exists in runbooks, in onboarding checklists, in architecture review templates. It is violated constantly.
The usual framing is compliance: untagged resources make cost reports harder to read. But the real risk is something different. Untagged resources cannot be owned. Resources without owners cannot receive budget alerts. Resources without budget alerts can accumulate spend invisibly โ for weeks, for months, for amounts that would have been caught in hours if they had been tagged.
In 2025, a compromised AWS sandbox account accrued approximately $1 million in cryptomining charges before detection. The account lacked ownership tags. Without tags to route alerts to a specific team, the spend accumulated within the organization's total cloud bill with no team receiving a notification. The missing tags were not a compliance failure โ they were the reason the incident was so expensive.
What QB8 Is Detecting
The governance gap detector fires on a simple condition: a resource has been billing for at least part of a 30-day window, the charges are real usage (not adjustments or credits), and the Tags column in the FOCUS billing export is null, empty, or an empty JSON object.
This is a governance state detector, not a temporal pattern detector. Unlike a spike (which requires a change in cost over time) or a scheduling miss (which requires a contrast between weekday and weekend billing), the untagged resource pattern has no required temporal element. A resource at a steady $5/day with no tags fires exactly as much as one that just appeared. The anomaly is the absence of attribution metadata โ the cost trajectory is irrelevant.
What Appears in FOCUS Billing Data
| FOCUS Field | Tagged (normal) | Governance gap (QB8 trigger) |
|---|---|---|
Tags |
{"env": "prod", "team": "platform", "cost-center": "cc-0039", "managed-by": "terraform"} |
NULL, "", or "{}" โ no key-value pairs present |
BilledCost |
Any positive value | Any positive value โ cost itself is not anomalous |
ChargeCategory |
Usage |
Usage โ QB8 filters to real usage charges only, not adjustments |
ConsumedQuantity |
Non-zero | Non-zero โ the resource is genuinely running, just untracked |
SubAccountId |
Maps to a known team account | May be a sandbox account, shared account, or unknown billing scope |
The FOCUS 1.0 specification defines the Tags column as a JSON string of key-value pairs. When a resource has no user-defined tags, the column is NULL or contains an empty JSON object ({}). Resources tagged only with AWS-internal system tags (like aws:cloudformation:stack-name) technically have a non-null Tags value but still provide zero cost allocation capability โ these represent a semantic gap that the basic null-check does not fully capture.
Industry Scale
| Metric | Value | Source |
|---|---|---|
| FinOps Foundation target: untagged cost rate | <10% of total cloud spend | FinOps Foundation KPI Working Group |
| FinOps Foundation target: tagging compliance | >90% of resources tagged | FinOps Foundation Compliance Working Group |
| Industry reality: actual untagged spend | 20โ40% of total cloud spend | eG Innovations industry analysis |
| Budget overrun correlated with poor tagging | 20โ30% annual budget overruns | eG Innovations industry analysis |
The gap between the FinOps Foundation's target (<10% untagged) and industry reality (20โ40% untagged) is not because teams are indifferent to tagging. It is because tagging compliance requires enforcement at resource creation โ a retroactive tagging effort on existing resources is expensive and rarely complete. Resources created manually through the console (not via IaC) are the most common source of tag drift.
Real-World Incidents
$1 million cryptomining in a compromised sandbox (Scale Factory, 2025): A sandbox AWS account lacking ownership tags accumulated approximately $1 million in EC2 charges from a cryptomining operation launched by an attacker who had compromised the account's credentials. The sandbox was part of a larger organization with "tens of millions in annual cloud spend." The missing ownership tags meant no team received a budget alert for the account. The spend blended into the organization's total until a manual review surfaced it. Tags were not the only control failure โ but their absence was specifically cited as the reason the spend was not routed to any team's alert queue.
$4,000 Elasticsearch cluster (AWS billing case study): A developer provisioned an Elasticsearch cluster manually (not via IaC, no tags applied) for a load test. The test completed. The cluster was not terminated. With no owner tag and no team aware of the resource, it ran until an engineer happened to notice it in the AWS console. No automated detection fired. The $4,000 is the lower bound โ the cluster could have run significantly longer.
$180,000/year from unmonitored drift (Firefly, Comtech case study): An organization's automated infrastructure drift โ resources created outside the IaC pipeline โ accumulated untagged and unmonitored assets. Without cost-center or team tags, no alerts were routed to the resource owners. Remediation: governance automation that flagged untagged resources and attributed them to owners. Hard savings: $180,000/year after remediation.
Detection Logic
SELECT resourceid, servicename, subaccountid,
COUNT(DISTINCT billing_day) AS days_seen,
SUM(daily_cost) AS total_cost_30d
FROM billing_by_day
WHERE
-- real usage charges only, not adjustments
chargecategory = 'Usage' AND chargeclass = 'Regular'
-- the last 30 days
AND billing_day >= CURRENT_DATE - 30
-- tags are absent
AND (tags IS NULL OR tags = '' OR tags = '{}' OR tags = 'null')
-- resource must be identifiable
AND resourceid IS NOT NULL AND resourceid != ''
GROUP BY 1, 2, 3
-- cost floor: suppress micro-resources below investigation threshold
HAVING total_cost_30d > 5.00
ORDER BY total_cost_30d DESC
The cost floor ($5 over 30 days in the example above) suppresses inherently untaggable micro-resources โ DNS query charges, CloudTrail delivery fees, and similar platform overhead that cannot be tagged regardless of governance posture. The FinOps Foundation notes that approximately 5โ10% of cloud resources are inherently untaggable. Setting the floor above the noise level surfaces only resources worth acting on.
The Gap: Semantically Untagged Resources
A resource tagged only with {"env": "prod", "owner": "unknown@company.com"} passes the null-check but is still unallocatable to a cost center or team. The governance gap that matters in practice is not just null tags โ it is the absence of mandatory cost allocation keys: cost-center, team, project, environment.
AWS Organizations tag policies can enforce required key names, but they apply only to resources created after the policy is configured, and only to supported resource types. Retroactive enforcement is manual. The most durable approach is to block resource creation (via SCPs or IaC guardrails) when mandatory tags are absent.
Fix Checklist
- Run the detection query and export the results: the output is a list of resource IDs with material spend and no tags. Sort by total_cost_30d descending. The top 10 rows are where to start.
- Tag or terminate, no third option: for each flagged resource, either apply the mandatory tag set (cost-center, team, environment) or terminate it. Leaving it untagged-but-running means it will reappear in next month's results.
- Find the creation path: resources created manually through the AWS console account for most tag drift. Any resource not created via IaC is a candidate for drift. Audit console users and enforce a policy: if it wasn't created via Terraform (or equivalent), it gets reviewed monthly.
- Enable AWS Organizations tag policies: tag policies can enforce key names and value formats on new resources in supported services. They do not retroactively tag existing resources but prevent new drift from the same sources.
- Add account-level budget alerts for sandbox and dev accounts: sandbox accounts in particular should have $0-tolerance budget alerts because they are the most common source of credential-compromise incidents and manual resource creation. Even without resource-level tagging, an account-level alert catches unexpected spend in the account.
- Establish a monthly tagging review cadence: the detection query takes minutes to run. Scheduling it monthly on all non-production accounts, with the output reviewed by the team that owns that account, creates an accountability loop without requiring full automation.
See if this pattern is in your billing data
The 5-question DropInFinOps assessment takes 2 minutes and tells you which anomaly patterns your current billing setup is positioned to catch โ and which ones are slipping through.
Take the free assessment โ