Homeβ€Ί Blogβ€Ί AWS Architecture Series #105 β€” Partial results look exactly like complete ones…
AWS Architecture AWS Architecture Series

AWS Architecture Series #105 β€” Partial results look exactly like complete ones

A tag policy cannot see an untagged resource, so AWS points at Resource Explorer and a tag:none query to find them. That tool has two modes which return different answers to the same question, the mode you get depends on a permission somebody did or did not hold, and the console does not announce which one you are looking at.

Verified against current vendor documentation on 7 November 2026. Pricing, limits and API behaviour were checked against the official docs on that date. Cloud services change fast — if you are reading this much later, treat the specifics as a starting point and re-check the linked sources.

Business Challenge

#104 ended on a gap: a tag policy governs the shape of tags that exist, so the resource with no tags is not non-compliant — it is unevaluated. The remedy AWS documents is a different service and a one-word query:

“To find untagged resources in your account, use AWS Resource Explorer with a query that uses tag:none.”

That works, and it is the right instrument. The care is in knowing which of two answers you are getting, because Resource Explorer will return results either way.

1Two index types, and the weaker one is the default you get by accident

“These indexes come in two types: Resource Explorer-owned indexes that provide immediate partial results, and user-owned indexes that provide complete results with automatic updates.”

Which you get is decided by a permission rather than a setting. With the read-only managed policy “you can immediately search in partial results”. For the other kind: “For complete resource inventory with automatic updates, you'll also need the iam:CreateServiceLinkedRole permission.”

So the completeness of your inventory depends on whether anyone who has ever opened Resource Explorer in that account happened to hold a role-creation permission. It is sticky once it happens — “After the service-linked role is created in your account by any user, subsequent users only need the permissions in the AWSResourceExplorerReadOnlyAccess managed policy to get complete results” — which means the state of your tooling is a function of who logged in first.

Fix

Before trusting an untagged-resource count, verify that Resource Explorer is using user-owned indexes with complete discovery enabled rather than returning immediate partial results. Confirm the required service-linked role exists, check which resource types are indexed and which accounts and Regions are in scope, and allow for eventual consistency. A complete index means complete discovery within Resource Explorer's supported scope — not an exhaustive inventory of every AWS resource.

2The partial mode is missing exactly the resources you are hunting

The scope of partial results is given in a parenthesis, and it is worth reading slowly:

“you can immediately search in partial results (all tagged resources and supported untagged resources created after the immediate resource discovery release).”

Tagged resources: all of them. Untagged resources: the ones created after a particular release. For a query whose entire purpose is finding untagged resources, the population at risk of being absent is the untagged resources that have existed longest — which in a tagging programme is precisely the backlog you are trying to size.

The failure is quiet in the way this series keeps finding. A tag:none search in partial mode returns a number. It is a real number. It is not the number you asked for, and nothing in the result distinguishes the two.

Fix

Treat a tag:none count from an account without the service-linked role as a lower bound, and say so wherever the figure is reported. With the role it is a better bound rather than a guaranteed total, because the answer is still bounded by the resource types Resource Explorer indexes and by the accounts and Regions in scope. A bound is useful; a bound presented as a total is how a tagging programme gets sized wrong at the start.

3Cross-Region and cross-account are separate opt-ins, and the data lags

Out of the box you are searching one Region. “you can search across multiple AWS Regions by enabling cross-Region search with a single click or API call to select an aggregator AWS Region”, and across accounts it is more: “Organizations can set up multi-account search by enabling trusted access and using AWS CloudFormation deployment.”

Three different scopes, then, each with its own enablement: this Region, all Regions, all accounts. An untagged-resource count is meaningless until you know which of the three produced it.

And the aggregated view is not instantaneous: “Resource Explorer, like many other AWS services, is eventually consistent”, with the example given being “Resource Explorer finding a resource in one AWS Region, and replicating that to the AWS Region that contains the aggregator index for the account.”

Fix

Record the scope and the timestamp next to any inventory figure. 4,812 untagged resources is not a fact; 4,812 untagged resources across 14 accounts and all Regions, aggregated in eu-west-1, as of Tuesday is one.

Architecture

Diagram: AWS Resource Explorer answers the untagged-resource question that a tag policy cannot, using a tag:none query, but it returns results from one of two index types. Resource Explorer-owned indexes provide immediate partial results covering all tagged resources and supported untagged resources created after the immediate resource discovery release, while user-owned indexes provide complete results with automatic updates and require the iam:CreateServiceLinkedRole permission. Which one an account has depends on the permissions held by whoever first used the service, and the result does not say which it came from. The diagram also shows three separate scopes, each with its own enablement: the current Region by default, cross-Region search by selecting an aggregator Region, and multi-account search through Organizations trusted access and a CloudFormation deployment. Resource Explorer is eventually consistent, so replication from a Region to the aggregator index takes time, and its quotas are fixed at ten views per Region and five search operations per second.

The same query, two populations

Resource Explorer-owned indexUser-owned index
AWS's description “immediate partial results” “complete results with automatic updates”
Covers All tagged resources, plus untagged ones “created after the immediate resource discovery release” The inventory
What you need AWSResourceExplorerReadOnlyAccess Also iam:CreateServiceLinkedRole, once, by anyone
How the result is labelled It is not

The last row is the architectural point. Two instruments with different calibration return the same shape of answer to the same question, and the difference is not in the output.

Three scopes, three enablements

ScopeWhat it takes
Current RegionNothing — “enabled by default in your AWS account with no setup steps required” since 6 October 2025
All Regions“a single click or API call to select an aggregator AWS Region”
All accounts“enabling trusted access and using AWS CloudFormation deployment”

Being on by default is a genuine improvement — the old version needed an index created in every Region before it could answer anything. It also means the service now returns results in accounts nobody configured, which is the condition under which a partial answer is most likely to be taken at face value.

What it costs, which is not nothing

“There are no charges to search for resources by using AWS Resource Explorer, including creating views, completing setup in AWS Regions, or searching for resources.” Then the qualifier: “In the process of building your resource inventory, Resource Explorer calls APIs on your behalf that may result in charges.”

The search is free; the indexing calls other services on your behalf. For most estates this is noise. It is worth knowing before someone enables complete indexing across several hundred accounts and then goes looking for what changed in the bill.

The quotas are fixed, and one of them bounds automation

“You cannot increase the quotas for AWS Resource Explorer.” Two matter: “Number of views in an AWS Region | 10” and “Maximum Search operations per second | 5”.

Five searches a second is ample for a human and tight for a nightly sweep that walks every account. Any tagging-compliance automation built on this needs to be paced, and it cannot be given more room by asking.

Why This Architecture Holds Up

Returning partial results beats returning nothing

The alternative design — refuse to answer until an index exists — is what the service used to do, and it meant the common case was an empty console and a setup task. Giving immediate partial answers makes the tool useful on first contact. The cost is that the two modes are indistinguishable at the point of use, which is a documentation problem more than a design one.

Gating the complete-indexing model on a service-linked role is consistent

A complete, continuously updated inventory means the service acting on your behalf across services, and that needs a role. Gating it on iam:CreateServiceLinkedRole is the ordinary AWS pattern and the right one. What it produces is the slightly odd property that an account's tooling quality is set by the permissions of whoever got there first.

Being honest about eventual consistency matters here specifically

A search service that quietly lagged would be worse than one that says so, because the whole point of an inventory is that you compare it against something. Naming the aggregator replication delay in the overview rather than a footnote lets you decide how fresh a figure has to be before you act on it.

Key Architecture Decisions

DecisionChoose thisBecause
Before reporting an untagged count Confirm complete indexing is in use, then state the scope it covers Without the service-linked role you have “partial results” and no indication of it; with it you have complete discovery within Resource Explorer's supported scope, which is not the same as every resource
Scope of any inventory figure State Region scope, account scope and timestamp Three different enablements produce three different numbers from one query
Organisation-wide tagging audit Trusted access plus the CloudFormation deployment, once Per-account searching will not aggregate and will not be comparable
Automating the sweep Pace it under five searches per second The quota is hard — “You cannot increase the quotas”
Relationship to tag policies Use both: the policy for shape, this for presence Neither sees what the other does

The audit worth running

Run tag:none in two accounts you know differ — one long-established, one recent — and compare the shape of the answers. If the old account returns suspiciously few untagged resources, you are probably looking at partial results, and the oldest part of your estate is the part missing.

Then check the aggregator Region is set and is the one your reporting expects. A figure aggregated in a Region nobody looks at is a figure that will be recomputed differently by the next person.

Finally, put the two numbers side by side. The tag policy compliance report from #104 counts resources whose tags are wrong; the tag:none count finds resources with no tags at all. Neither is the tagging programme's size on its own, and the sum is the first honest estimate of it.

Closing Thought

The pattern that runs through this fortnight of posts is a control or a tool that is precisely described and quietly narrower than its name. A tag policy that does not require tags. A block that does not revoke. A lock that defends existence and not readability. This one is the measuring instrument, and it has the same property: two calibrations, one output format.

What makes it worth the attention is where it sits. An inventory is the thing every other number gets compared against, so an inventory that is quietly partial does not produce one wrong answer. It produces a baseline that makes every subsequent comparison wrong in the same direction, and nobody re-derives a baseline.

The fix is small and it is a habit rather than a configuration: write down what the number counted, over what scope, at what time, and under which index. Three of those four are free to record and the fourth takes one API call.

Next in this series

Cost & Governance — AWS cost allocation tags: why activating a tag key changes nothing about the past, how long activation takes to appear in billing data, and what user-defined and AWS-generated keys each cover.

Comments

How was your experience?
Your feedback helps improve this site.
PoorExcellent