Blast radius analysis
Blast radius analysis shows all resources that a change to one resource instance, or its destruction, can affect.
What is blast radius?
When a resource changes, its dependents can also need an update or a replacement. Stategraph computes the blast radius from the dependency graph of the Terraform configuration. The graph follows references into linked states, so it includes dependents in other states.
Change
Blast radius
Each can need an update or a replacement.
aws_vpc.main.Its blast radius holds six resources: two subnets, a security group, an instance, a DB subnet group, and an RDS cluster.
Get the blast radius
In the console, Blast Radius is under Insights.
CLI
- Get your tenant ID:
# List your tenants
stategraph user tenants list
Output:
id name
------------------------------------ ------
550e8400-e29b-41d4-a716-446655440000 my-org
- Get the state ID:
# List states for a tenant
stategraph states list --tenant 550e8400-e29b-41d4-a716-446655440000 --format json
Output:
{
"results": [
{
"created_at": "2024-01-15T10:30:00Z",
"group_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "networking",
"workspace": "production"
}
]
}
- Query the blast radius:
# For aws_instance.web
stategraph states instances blast-radius \
--state a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
"aws_instance.web"
# For module.vpc.aws_subnet.public[0]
stategraph states instances blast-radius \
--state a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
"module.vpc.aws_subnet.public[0]"
Output:
address kind state instances depends_on
------------------ -------- ---------- --------- ----------
* aws_instance.web resource networking 1 0
aws_eip.web resource networking 1 1
Read the results
The table has one row for each block of the configuration that the change reaches, nearest first:
address: the block address.*marks the block of the queried instance.kind: the block type, for exampleresource,data,module,variable,output, orlocals.state: the state of the block. The blast radius can span states, so this can differ from the queried state.instances: the number of instances of the block.depends_on: how many of the listed blocks it depends on.
--format json returns the graph: nodes, the edges between them, root_id (the queried block), total_nodes, and truncated.
--max-depth caps the dependency hops (default 100), and --limit caps the blocks (default 1000). When a cap cuts the result, the CLI prints a warning to stderr.
A change certainly affects the blocks one hop away, and likely affects the blocks two or three hops away. Blocks four or more hops away can be affected, depending on the change type.
High-risk patterns
Network foundation resources
VPCs, subnets, and security groups often have a large blast radius:
- aws_subnet.public20+ resources
- aws_subnet.private30+ resources
- aws_security_group.web15+ resources
- aws_internet_gateway.main10+ resources
aws_vpc.main.Each has 10 or more resources of its own in the blast radius.
IAM roles
Roles that many services use:
- aws_lambda_function.apidistance 1
- aws_ecs_task_definition.workerdistance 1
- aws_codebuild_project.builddistance 1
- many more
aws_iam_role.application, each at distance 1 from the role.Data resources
Databases and storage that services depend on:
- aws_rds_cluster_instance.primary
- aws_rds_cluster_instance.replica
- aws_secretsmanager_secret.db_credentials
- aws_lambda_function.processor
aws_rds_cluster.main.Reduce the blast radius
For loose coupling, use data sources instead of direct references:
# Higher coupling (larger blast radius)
resource "aws_instance" "web" {
subnet_id = aws_subnet.main.id
}
# Lower coupling
data "aws_subnet" "main" {
tags = { Name = "main" }
}
resource "aws_instance" "web" {
subnet_id = data.aws_subnet.main.id
}
Put related resources behind a module boundary:
module "networking" {
source = "./modules/networking"
}
module "compute" {
source = "./modules/compute"
subnet_id = module.networking.subnet_id # Single connection point
}
Split large states into smaller, focused states:
networking/ → VPCs, subnets, security groups
compute/ → EC2 instances, ASGs
data/ → RDS, DynamoDB
Comparing blast radius
Compare the blast radius of resources to set change priorities:
| Resource | Blast radius size | Risk level |
|---|---|---|
| aws_vpc.main | 45 resources | High |
| aws_security_group.web | 12 resources | Medium |
| aws_instance.worker | 2 resources | Low |
The same resource can have a different blast radius in each workspace:
| Workspace | aws_vpc.main blast radius |
|---|---|
| Production | 150 resources |
| Staging | 50 resources |
| Dev | 10 resources |
SQL queries
Find resources with large blast radius
Blast radius takes one CLI call per resource. A script can loop over all instances:
#!/bin/bash
STATE_ID="a1b2c3d4-e5f6-7890-abcd-ef1234567890"
# Get all instance addresses (--paginate needs the ORDER BY to read every page)
stategraph sql query --paginate --format json \
"SELECT address FROM instances WHERE state_id = '$STATE_ID' ORDER BY address" | \
jq -r '.[].address' | while read -r instance; do
count=$(stategraph states instances blast-radius --state "$STATE_ID" --format json "$instance" 2>/dev/null | \
jq '[.nodes[] | select(.is_seed | not)] | length')
printf '%s\t%s\n' "$count" "$instance"
done | sort -rn | head -20
Find highly connected resources
Instances that depend on the most resources:
SELECT address, array_length(dependencies, 1::integer) as dep_count
FROM instances
WHERE array_length(dependencies, 1::integer) > 0
ORDER BY array_length(dependencies, 1::integer) DESC
LIMIT 20
Best practices
- Before you change critical infrastructure, apply a production change, or start maintenance, check the blast radius of each component and whether changes cascade to critical services.
- Plan the change window from the impact. Plan communication and a rollback in case the blast radius was underestimated.
- Mark resources with a large blast radius as high risk, and take extra care with their changes.
- Prefer several small changes to one large change.
- Test in staging, to make sure that changes do not cascade unexpectedly.
Limitations
- Blast radius shows structural dependencies, not runtime dependencies.
- It does not track external dependencies, such as DNS or external APIs.
- Changes that do not affect the dependency graph can still cause problems.
Next steps
- Graph Explorer: see the dependencies.
- Timeline: follow changes.
- Query: query with SQL.