The situation
Acme’s resource estate, as of this week:
- 22 AWS accounts under one Organization.
- 15 Regions in active use across those accounts (most accounts in 2-3 Regions, a few spread wider).
- Roughly 45,000 taggable AWS resources: EC2 instances, EBS volumes, RDS, S3 buckets, Lambdas, CloudFormation stacks, CloudWatch log groups, VPCs, and the long tail.
Five recurring search questions that no-one can answer in under an hour today:
- “Show me every S3 bucket tagged
Env=prodacross the org.” - “Where are all the untagged EC2 instances hiding?”
- “Which Regions is account
555555555555using? Which Regions is it not using but could still be billing us for idle resources?” - “Which Lambdas haven’t been updated in 180 days?”
- “Show me every resource that has a
CostCentertag but noOwnertag.”
Each question is, in principle, answerable. In practice, answering any one of them today means: open the AWS CLI with each account’s credentials in turn, iterate over Regions, call the service-specific describe API (different shape per service), join on tags (different tag API per service), and assemble locally. It’s not hard; it’s just slow, manual, and frequently skipped.
What actually matters
The first question is what shape of question are we actually answering? Tag-based discovery (“find me resources with these tags”) is a different problem from configuration-attribute filtering (“find me resources where this property is set this way”). The two need different indexes underneath. A tool optimised for tag discovery will be shallow on per-service configuration; a tool optimised for configuration depth will carry per-item cost that pinches at estate scale. Knowing which shape the question takes, and which the team will ask most often, decides which index pays for itself.
The second is where does the aggregation happen? Fanning out N accounts × M Regions from the caller’s machine is what the spreadsheet approach already does. Any real answer has to put the aggregation server-side, in a managed index that’s continuously updated by the platform, so the query is one call with one result set rather than 330 calls and a join. The aggregation surface also has to compose with the organisation boundary: a single-account tool still leaves 21 fan-outs on the table.
The third is freshness vs. cost. An index that updates within seconds of a create/delete is great for “did we just leak a public bucket”; an index that updates hourly is fine for “where are the untagged instances”. The continuously-updated path tends to ride on existing audit telemetry the team already pays for; the deeper index records every configuration change for every resource, which is what makes the per-item cost shape what it is.
The fourth is setup overhead per account. Anything that requires per-account, per-Region click-through doesn’t scale to 22 × 15. The discovery layer has to be deployable from the org admin, trusted access, delegated admin, one-shot rollout, otherwise the operational tax dwarfs the answer.
The fifth is what’s in scope. Some questions are tag-only and resolve in seconds against a tag index. Some require configuration fields the tag index doesn’t carry and have to fall back to the deeper compliance store. Some span both. The right answer is often two indexes side by side, each used where it’s strong, rather than forcing one tool to do both jobs.
What we’ll filter on
- Cross-account aggregation, one query spans many accounts?
- Cross-Region aggregation, one query spans many Regions?
- Tag-based search, find by tag key/value?
- Deep config filter, find by arbitrary resource attribute (not just tag)?
- Query latency, seconds, or a batch job?
- Setup cost, what’s the cost and effort to enable?
The resource-discovery landscape
-
Resource Explorer, per-account aggregator. A managed index in each Region; the chosen aggregator Region cross-indexes all other Regions’ data. Continuously updated. Free. Query via
resource-explorer-2:Search. Limitations: supports most resource types AWS publishes, but not every service; tag queries are first-class; free-text works on names and ARNs. -
Resource Explorer, multi-account via delegated admin. Set up in the org admin account with
organizations:EnableAWSServiceAccess, designate a delegated admin account, and that account’s aggregator indexes every member account’s resources. One query, org-wide. -
Config Aggregator + Advanced Queries. Aggregator in one account pulls CI data from others. Advanced Queries are SQL over the CI schema. Depth of configuration data (encryption state, network attachment, lifecycle policy) not available in Resource Explorer. Config recorder must be on; per-item storage costs apply.
-
Resource Groups Tagging API. Single-account, tag-based. The building block; not the answer for org-wide queries unless you build the aggregation yourself.
-
Tag Editor console. UI over (4). Fine for ad-hoc; same single-account scope.
-
Third-party. Varies. Out of scope for this post.
Side by side
| Option | Cross-account | Cross-Region | Tag search | Deep filter | Latency | Setup cost |
|---|---|---|---|---|---|---|
| Resource Explorer (account aggregator) | ✗ | ✓ | ✓ | Limited | Seconds | Free, minutes |
| Resource Explorer (org + delegated admin) | ✓ | ✓ | ✓ | Limited | Seconds | Free, minutes |
| Config Aggregator + AQ | ✓ | ✓ | ✓ | ✓ | Seconds | Per-CI cost, non-trivial |
| Tagging API (single acct) | ✗ | ✗ | ✓ | ✗ | Seconds | Free |
| Tag Editor | ✗ | ✓ (per acct) | ✓ | ✗ | Seconds | Free |
| Third-party | ✓ | ✓ | ✓ | ✓ | Varies | Subscription |
For Acme’s five questions, the answer is a combination: Resource Explorer (org aggregator) for questions 1, 2, 3, 5; Config aggregator for question 4 (if Config is enabled) or a targeted Lambda polling ListFunctions org-wide.
How the aggregator indexes see the estate
Resource Explorer in depth
Enabling Resource Explorer is three steps per account: enable indexes in each Region you care about, designate one as the aggregator, and (for org-wide) enable trusted access and register a delegated admin.
Per account, per Region:
aws resource-explorer-2 create-index \
--type LOCAL \
--region eu-central-1
Promote one Region to aggregator:
aws resource-explorer-2 update-index-type \
--arn arn:aws:resource-explorer-2:us-east-1:111122223333:index/... \
--type AGGREGATOR
For org-wide, from the management account:
aws organizations enable-aws-service-access \
--service-principal resource-explorer-2.amazonaws.com
aws resource-explorer-2 register-delegated-administrator \
--delegated-admin-account-id 555555555555 \
--service-principal resource-explorer-2.amazonaws.com
Then in the delegated admin account:
aws resource-explorer-2 create-index --type LOCAL --region eu-west-1
aws resource-explorer-2 update-index-type --type AGGREGATOR --region eu-west-1
# and designate it as the org aggregator in the console or via CLI
Queries
Resource Explorer’s query language is a set of operators that can be combined:
tag.<key>:<value>, match tag key/value.tag:<key>, match any resource that has that tag key.-tag:<key>, exclude resources with that tag key.service:<service>, filter by service (s3,ec2,lambda, etc.).region:<region>, filter by Region.resourcetype:<service>:<type>, filter by exact resource type.<free text>, matches names and ARNs.
Question 1 (“every S3 bucket tagged Env=prod”):
aws resource-explorer-2 search \
--query-string 'service:s3 resourcetype:s3:bucket tag.Env:prod' \
--max-results 1000
Question 5 (“resources with CostCenter tag but no Owner tag”):
aws resource-explorer-2 search \
--query-string 'tag:CostCenter -tag:Owner'
Question 2 (“untagged EC2 instances”):
aws resource-explorer-2 search \
--query-string 'resourcetype:ec2:instance -tag:Env -tag:Owner -tag:Team'
Results come back within seconds. Each hit includes the resource ARN, type, Region, owning account ID, and tags. For cross-account queries against the org aggregator, the owning account is the field that lets you route follow-up actions.
When to reach for Config
Resource Explorer is great at “what resources do we have that look like X.” It’s deliberately shallow on service-specific attributes, the resource’s tags, type, Region, and ARN are first-class; the resource’s configuration (is this RDS instance encrypted? does this bucket have versioning? when was this Lambda last updated?) generally isn’t.
Config Aggregator + Advanced Queries is where the deep attribute filter lives:
SELECT
resourceId,
awsRegion,
accountId,
configuration.storageEncrypted,
configuration.engine
FROM
aws_config_aggregator
WHERE
resourceType = 'AWS::RDS::DBInstance'
AND configuration.storageEncrypted = false
Answering “every unencrypted RDS in the estate” is trivial in Config; Resource Explorer can’t do it at all.
The rule of thumb: Resource Explorer for tag-based discovery, Config for configuration-attribute queries. If both are available, which is common, Resource Explorer is the faster path for “find me the resource” and Config is the authoritative path for “tell me about the resource.”
A worked estate audit
First week with both tools enabled.
Question 1. Resource Explorer query, org aggregator, service:s3 resourcetype:s3:bucket tag.Env:prod. 47 buckets, spread across 9 accounts, 6 Regions. 200ms round-trip.
Question 2. Resource Explorer query, resourcetype:ec2:instance -tag:Env -tag:Owner -tag:Team. 83 instances, mostly in sandbox accounts, one in production. The production one triggers a follow-up investigation.
Question 3. Combination. Query aws resource-explorer-2 list-indexes for account 555555555555 shows which Regions have been enabled. Cross-referencing with billing data (Cost Explorer grouped by Region) flags four Regions with spend but no Resource Explorer index, which suggests either resources that aren’t indexable (billing metadata, support plans), or resources in Regions that hadn’t been discovered.
Question 4. Resource Explorer can return Lambdas; it doesn’t carry LastModified. Config’s Advanced Query against aggregated CI data does:
SELECT resourceId, awsRegion, accountId, configuration.lastModified
FROM aws_config_aggregator
WHERE resourceType = 'AWS::Lambda::Function'
AND configuration.lastModified < '2027-01-01'
Returns 38 functions, half of which turn out to be abandoned and scheduled for deletion, half of which are deliberate.
Question 5. Resource Explorer, tag:CostCenter -tag:Owner. 312 resources. Fed into a tagging-hygiene ticket that enforces Owner on every resource with CostCenter via a Config rule in the next quarter.
Total time for the audit: about two hours, most of that writing the queries. The same audit last quarter took four days.
What’s worth remembering
- Resource Explorer is the purpose-built answer for tag-based, cross-account, cross-Region discovery. One managed index per Region, one aggregator Region per account, one org-wide aggregator in a delegated admin account.
- Query language is tag-first.
tag.<key>:<value>,tag:<key>,-tag:<key>, plusservice,region,resourcetype, and free-text for names and ARNs. - Config Aggregator is the deep-attribute alternative. When the question depends on resource configuration (encryption, engine version, last-modified), Config’s CI data has it and Resource Explorer doesn’t.
- Org-wide requires trusted access and a delegated admin.
organizations:EnableAWSServiceAccessforresource-explorer-2.amazonaws.com, thenregister-delegated-administrator, then aggregator in the admin account. - Each account picks an aggregator Region. Local indexes exist per Region; one Region’s index becomes the aggregator and pulls from the others in the same account.
- Tagging API and Tag Editor are the single-account building blocks. Useful for ad-hoc in one account; scale with automation to many accounts.
- CloudTrail drives updates. Resource Explorer refreshes indexes when CloudTrail records creates, updates, and deletes. Accounts that disable CloudTrail see stale indexes.
- The query cost is free; the index storage is free. Resource Explorer is one of the few services that’s genuinely cost-free to enable. Config is not, its per-item costs are worth respecting at scale.
The audit that used to take four days takes two hours because the correct tool was built for the correct question. Resource Explorer’s genuine value is in the combination: org-wide, cross-Region, tag-based search with no custom infrastructure. For every “where are all the X?” question, the answer is an AWS CLI call and a coffee, not a spreadsheet and a week.