Resource Types
Stategraph counts the resources of each Terraform resource type, such as aws_instance or google_compute_instance, across all your states. Resource types are the building blocks of Terraform configurations. See the counts in the console under Inventory > Resource Types, get them with the API, or analyze them with SQL.
Counts with the API
Get the number of instances of each type in one state. To get STATE_ID, see Instances.
curl "http://localhost:8080/api/v1/states/$STATE_ID/resources/summary" \
-H "Authorization: Bearer $STATEGRAPH_API_KEY"
Response:
{
"aws_instance": { "instances": 20 },
"aws_security_group": { "instances": 15 },
"aws_subnet": { "instances": 6 },
"aws_iam_role": { "instances": 12 }
}
Tenant-wide breakdown
The tenant endpoint gives, for each state and type, how many resources the state declares and how many instances are deployed. The console shows the same data under Settings > Resource Types. Add state_id for one state:
curl "http://localhost:8080/api/v1/tenants/$TENANT_ID/resource-types" \
-H "Authorization: Bearer $STATEGRAPH_API_KEY"
Response:
{
"resource_types": [
{
"state_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"state_name": "networking",
"type": "aws_subnet",
"resource_count": 2,
"instance_count": 6
}
],
"total_resources": 2,
"total_instances": 6
}
instance_count is larger than resource_count when count or for_each expands one address into several objects. A type with nothing deployed has no entry.
Type analysis
Count all types
SELECT type, count(*) as type_count
FROM resources
GROUP BY type
ORDER BY count(*) DESC
Types by provider
provider holds the full provider source address, such as provider["registry.terraform.io/hashicorp/aws"]. Match it with LIKE.
AWS resources:
SELECT type, count(*) as type_count
FROM resources
WHERE provider LIKE '%hashicorp/aws%'
GROUP BY type
ORDER BY count(*) DESC
Google Cloud resources:
SELECT type, count(*) as type_count
FROM resources
WHERE provider LIKE '%hashicorp/google%'
GROUP BY type
ORDER BY count(*) DESC
Azure resources:
SELECT type, count(*) as type_count
FROM resources
WHERE provider LIKE '%hashicorp/azurerm%'
GROUP BY type
ORDER BY count(*) DESC
Unique types per state
MQL does not support count(DISTINCT ...). Dedupe with a CTE, then count:
WITH state_types AS (
SELECT state_id, type
FROM resources
GROUP BY state_id, type
)
SELECT state_id, count(*) AS types
FROM state_types
GROUP BY state_id
ORDER BY types DESC
Common resource types
| Type | Description |
|---|---|
aws_instance |
EC2 instances |
aws_security_group |
Security groups |
aws_iam_role |
IAM roles |
aws_s3_bucket |
S3 buckets |
aws_subnet |
VPC subnets |
aws_vpc |
Virtual private clouds |
aws_lambda_function |
Lambda functions |
aws_db_instance |
RDS instances |
google_compute_instance |
Compute Engine VMs |
google_storage_bucket |
Cloud Storage buckets |
google_container_cluster |
GKE clusters |
google_sql_database_instance |
Cloud SQL instances |
azurerm_virtual_machine |
Virtual machines |
azurerm_storage_account |
Storage accounts |
azurerm_kubernetes_cluster |
AKS clusters |
azurerm_sql_server |
SQL servers |
Type-specific queries
EC2 instances by type
SELECT i.attributes#>>'{instance_type}' AS instance_type, count(*) AS instance_count
FROM instances AS i
INNER JOIN resources AS r
ON i.resource_address = r.address AND i.state_id = r.state_id
WHERE r.type = 'aws_instance'
GROUP BY i.attributes#>>'{instance_type}'
ORDER BY count(*) DESC
S3 buckets by region
SELECT i.attributes#>>'{region}' AS region, count(*) AS region_count
FROM instances AS i
INNER JOIN resources AS r
ON i.resource_address = r.address AND i.state_id = r.state_id
WHERE r.type = 'aws_s3_bucket'
GROUP BY i.attributes#>>'{region}'
ORDER BY count(*) DESC
RDS instances by engine
SELECT i.attributes#>>'{engine}' AS engine, count(*) AS engine_count
FROM instances AS i
INNER JOIN resources AS r
ON i.resource_address = r.address AND i.state_id = r.state_id
WHERE r.type = 'aws_db_instance'
GROUP BY i.attributes#>>'{engine}'
ORDER BY count(*) DESC
Lambda functions by runtime
SELECT i.attributes#>>'{runtime}' AS runtime, count(*) AS runtime_count
FROM instances AS i
INNER JOIN resources AS r
ON i.resource_address = r.address AND i.state_id = r.state_id
WHERE r.type = 'aws_lambda_function'
GROUP BY i.attributes#>>'{runtime}'
ORDER BY count(*) DESC
Resource categories
Compute resources
SELECT type, count(*) as type_count
FROM resources
WHERE type IN (
'aws_instance',
'aws_lambda_function',
'aws_ecs_service',
'google_compute_instance',
'azurerm_virtual_machine'
)
GROUP BY type
ORDER BY count(*) DESC
Storage resources
SELECT type, count(*) as type_count
FROM resources
WHERE type IN (
'aws_s3_bucket',
'aws_ebs_volume',
'google_storage_bucket',
'azurerm_storage_account'
)
GROUP BY type
ORDER BY count(*) DESC
Network resources
SELECT type, count(*) as type_count
FROM resources
WHERE type IN (
'aws_vpc',
'aws_subnet',
'aws_security_group',
'aws_network_interface',
'google_compute_network',
'google_compute_subnetwork',
'azurerm_virtual_network',
'azurerm_subnet'
)
GROUP BY type
ORDER BY count(*) DESC
Security resources
SELECT type, count(*) as type_count
FROM resources
WHERE type IN (
'aws_iam_role',
'aws_iam_policy',
'aws_iam_user',
'aws_kms_key',
'aws_secretsmanager_secret'
)
GROUP BY type
ORDER BY count(*) DESC
Type distribution analysis
Types per workspace
SELECT state_id, type, count(*) as type_count
FROM resources
GROUP BY state_id, type
ORDER BY state_id, count(*) DESC
New resource types
Types in only one state can be new additions:
WITH type_states AS (
SELECT type, state_id
FROM resources
GROUP BY type, state_id
)
SELECT type, count(*) AS states_count
FROM type_states
GROUP BY type
HAVING count(*) = 1
ORDER BY type
Most common types
SELECT type, count(*) as type_count
FROM resources
GROUP BY type
ORDER BY count(*) DESC
LIMIT 10
Monitoring type growth
To track type growth, compare the counts at regular intervals:
SELECT type, count(*) as type_count
FROM resources
GROUP BY type
ORDER BY count(*) DESC
Save these queries to a dashboard. Check that the type distribution is appropriate, and compare the expected and actual counts to find drift and unexpected types.
Next steps
- Instances: browse all instances.
- Modules: view by module.
- Query: advanced queries.
- Dashboards: save type queries.