See it as a diagram
Everything below, as a diagram you can edit. Describe yours and see it in seconds.
No account needed · Editable canvas, not a picture
The rule: would removing it change the mental model
For every resource, ask whether a reader who never sees it would end up with a wrong understanding of the system. An SQS queue between two services changes the model completely: it makes the coupling asynchronous, introduces retries, and creates a backlog to watch. A KMS key does not; encryption at rest is assumed, and its absence would be the notable fact.
That single test sorts almost everything. Resources that carry architectural meaning become nodes. Resources that carry configuration meaning become labels, captions, or notes. Resources that carry neither, and every account has hundreds of them, stay out of the picture and live in the inventory.
The services that always earn a box
Entry points, because they define how traffic arrives: Route 53, CloudFront, API Gateway, ALB and NLB, and any public endpoint. Compute, because it is what runs: EC2 auto scaling groups as one node, ECS or Fargate services, Lambda functions, EKS node groups. State, because it is what you can lose: RDS and Aurora clusters, DynamoDB tables, S3 buckets that hold something the workload depends on, ElastiCache, OpenSearch.
The asynchronous backbone, because it changes failure behaviour: SQS queues with their dead letter queues, SNS topics, EventBridge buses, Kinesis streams, MSK clusters, Step Functions state machines. And the boundaries, drawn as containers rather than icons: account, region, VPC, availability zone, subnet tier.
What belongs in a caption instead of a box
Identity and secrets: IAM roles, policies, and the attachments between them, Secrets Manager secrets, SSM parameters. In a mid-sized Terraform stack these outnumber the resources a reader cares about, and the attachment objects carry no architectural information at all. Put the calling role on the edge and the rest in an identity note, as described in showing IAM without drowning the diagram.
Configuration and observability: security group rules (better as edge labels showing what they allow), route tables (better as a label on the subnet zone), ACM certificates, CloudWatch log groups, alarms, dashboards, autoscaling policies, and every resource whose name ends in a random suffix.
Everything left out still has to exist somewhere. That is what the inventory table in the generated architecture doc is for, so the diagram can stay editorial while the documentation stays complete.
| Terraform type | Diagram treatment | | --- | --- | | aws_cloudfront_distribution, aws_lb, aws_apigatewayv2_api | Node, always | | aws_ecs_service, aws_lambda_function, aws_autoscaling_group | Node, always | | aws_rds_cluster, aws_dynamodb_table, aws_s3_bucket | Node, always | | aws_vpc | Container, carrying its cidr_block | | aws_subnet, aws_nat_gateway, aws_security_group | Nested or rolled up, not a top-level box | | aws_iam_role, aws_iam_policy, aws_iam_role_policy_attachment | Counted in a note, never a box | | aws_cloudwatch_log_group, aws_cloudwatch_metric_alarm, aws_route53_record | Counted in a note, never a box |
A node budget, and what to do when you blow it
The standard Datadef generates against aims for 12 to 20 nodes with no more edges than nodes, and allows 25 to 40 when someone explicitly asked for depth. Forty is the ceiling, not the target. Past it, split by question rather than by shrinking: a context diagram of systems and their neighbours, a workload diagram of the request path, a network diagram of subnets and routes, and a data diagram of stores and flows.
When Datadef generates from a Terraform repository, that editorial pass is code rather than model judgment. Every resource type carries one of three weights. Major means a box the reader came for: aws_lb, aws_ecs_service, aws_lambda_function, aws_rds_cluster, aws_dynamodb_table, aws_s3_bucket. Minor means include when there is room and otherwise roll up: aws_subnet, aws_security_group, aws_sqs_queue, aws_nat_gateway. Glue means never a box under any circumstance: aws_iam_role, aws_iam_policy, aws_iam_role_policy_attachment, aws_cloudwatch_log_group, aws_cloudwatch_metric_alarm, aws_route53_record.
The budget on top of that is arithmetic. Each module may draw eight nodes, or sixteen when that one module accounts for more than half of everything visible in the repository. Repeated minor types inside a module collapse into one node labelled with the count and the members, in the shape "SQS queues ×4: orders, orders dlq, exports, exports dlq". If the plan still exceeds forty nodes, a second stricter pass folds the remaining lone minors into one "Supporting resources" node carrying its own count. That is how a first completeness pass over a 123-resource repository, which drew 62 boxes and read like a phone book, became a canvas of roughly 36. Nothing is discarded: the counts ride on the nodes and the full inventory is the generated module reference table.
On an existing canvas, canvas_suggest_simplifications in the MCP server proposes which nodes to collapse, so an agent session can do the trimming with you rather than you arguing with a layout.
FAQ
Should security groups appear in an AWS architecture diagram?
Do I need to show IAM roles?
How many nodes is too many for one AWS diagram?
What about services that only exist in one environment?
Where does the full resource list go?