Naming matters, especially for AWS resources. A good naming convention will help your team move quickly during critical moments. It will make incident resolution much easier and even simplify redeploying resources.
One part of a naming convention is… well. The “randomness” of names and why you should embrace it.
The list I follow is as follows
Weird list no?
A name can mislead you in so many ways. They act as red herrings during debugging sessions. Take, for example, a security group named “allow_nlb_to_eks.” That suggests it allows the ELB to communicate with the EKS cluster… Right?
Well, maybe. Initially, probably yes. But over time, refactors happen. The cluster gets deleted, but the security group remains because it also handled a database connection to a Lambda function. Renaming it would trigger a recreation, and nobody wants downtime. The security group still exists but has lost any original meaning. The name betrays anyone who wants to debug it. The persons responsible for it are long gone. The downtime timer keeps going up. You’ve wasted so much time on this unrelated security-group when you actually needed the real “allow_nlb_to_eks_v2” security group. Or do you?
Very important resources on AWS require unique names. So when you want to redeploy something, a hardcoded static name can be the blocker in the end. An IAM role with that name already exists, a security-group with that name already exists or even worse… a secret or KMS key. Deleting those last two ain’t that easy as they have a deletion protection timer on them. So that module that creates a secret with the name “very_important_secret” can’t be redeployed (or deployed next to each other) as the secret already exists!
It is almost tradition that system administrators gave resources a name that felt close to them. How many datacenters have their original servers named after LOTR places and persons? But when the company growed, suddenly the naming list became very short. Nobody really wants to kill the tradition but in the end the names out of books are gone. Your life-partner became your ex-partner but the critical database still bear there name. It is a very limited list and after a while the good names become… very bad names.
When a resource can be spun up without me defining a name, I do so. Some resources come up empty with purely an ID/ARN (which you can count as a name). Some receive a random one from Terraform or AWS.
In AWS one of the most prolifics in this sense are security-groups. If you do not define anything, a random name will be generated for you and I love it. The name is so random, that only if you encounter it many times you’ll associate it to some resources but if it vanishes, it will also vanish from my mind.
I love the name sg-0123abc456def7890
, it tells me
nothing.
Honestly, that’s mostly it. If that doesn’t work, I go to the faulty resource, check which security groups are attached, and review their rules. Check up on the NACLs and the other twenty network firewalls that have been introduced since the inception of our environment.
But I never trust the name to provide any useful information.
No. Use tags. A fun one I like to use is the File tag, which indicates which Terraform file created the resource.
tags = {
File = "rds.security-group.tf"
}
You can add more like Description
but I’ve never
actually done that. I don’t trust the human who wrote it (that will
probably be me).
Ok, sometimes a name is… required. Why AWS doesn’t generate random
names for these cases, I have no idea. But when that happens, I hope
Terraform provides a name_prefix
. This adds a timestamp of
resource creation after the specified name.
Security groups allow this
resource "aws_security_group" "example" {
name_prefix = "allow_nlb_to_eks"
# ... other configuration ...
This generates a security group with the name allow_nlb_to_eks-20250225095045107900000005.
Now, the chance of a collision (where two different teams create a security group with the very generic name allow_nlb_to_eks) becomes extremely low thanks to the timestamp (and humans are really bad at unique names so that allow_nlb_to_eks will happen).
Very handy for clusters, S3 buckets, IAM roles,… which all have unique naming requirements!
Sure, why not? Sometimes the resource doesn’t support
name_prefix
.
Here we use another resource coming from the random_provider
resource "random_id" "sg" {
prefix = "allow_nlb_to_eks-"
byte_length = 8
}
resource "aws_security_group" "example" {
name = random_id.sg_
# ... other configuration ...
This results in allow_nlb_to_eks-e5cbb5f74a95f7fe
. I
feel this one is handier when there is a naming length limit and the
name_prefix of Terraform does generate a very very long timestamp.
Especially ELBs will hit this one.
You started to love the timestamp format of Terraform but want it much shorter? No problem (Though this increases the risk of collisions).
Make sure to include ignore_changes
, or Terraform will
recreate the resource every run.
resource "aws_security_group" "example" {
name = "allow_nlb_to_eks-${substr(timestamp(),0,10)}"
ignore_changes = ["name"]
# ... other configuration ...
We begrudgingly hate them, try to explain them why they are wrong in 100 different ways, and then accept our fate. We implement the static name that will probably cause issues in the future. But hey, that’s a problem for future Tom!
Not all are tested, this is quickly gathered and sadly S3 has a lot of filters with prefix in the name. I occasionally remove the incorrect ones when I encounter them.
Readable name | Resource name | Option |
---|---|---|
Connector Profile | aws_appflow_connector_profile | bucket_prefix |
Flow | aws_appflow_flow | bucket_prefix |
Group | aws_autoscaling_group | name_prefix |
Launch Configuration | aws_launch_configuration | name_prefix |
Report Plan | aws_backup_report_plan | s3_key_prefix |
Compute Environment | aws_batch_compute_environment | compute_environment_name_prefix |
Job Definition | aws_batch_job_definition | arn_prefix |
Budget | aws_budgets_budget | name_prefix |
Public Key | aws_cloudfront_public_key | name_prefix |
Trail | aws_cloudtrail | s3_key_prefix |
Metric Stream | aws_cloudwatch_metric_stream | name_prefix |
Document Classifier | aws_comprehend_document_classifier | version_name_prefix |
Entity Recognizer | aws_comprehend_entity_recognizer | version_name_prefix |
Conformance Pack | aws_config_conformance_pack | delivery_s3_key_prefix |
Delivery Channel | aws_config_delivery_channel | s3_key_prefix |
Organization Conformance Pack | aws_config_organization_conformance_pack | delivery_s3_key_prefix |
Instance Storage Config | aws_connect_instance_storage_config | bucket_prefix |
Report Definition | aws_cur_report_definition | s3_prefix |
Endpoint | aws_dms_endpoint | no_hex_prefix |
Cluster | aws_docdb_cluster | cluster_identifier_prefix |
Cluster Instance | aws_docdb_cluster_instance | identifier_prefix |
Cluster Parameter Group | aws_docdb_cluster_parameter_group | name_prefix |
Event Subscription | aws_docdb_event_subscription | name_prefix |
Subnet Group | aws_docdb_subnet_group | name_prefix |
Table | aws_dynamodb_table | key_prefix |
Table Export | aws_dynamodb_table_export | s3_prefix |
Key Pair | aws_key_pair | key_name_prefix |
Launch Template | aws_launch_template | name_prefix |
Verified Access Endpoint | aws_verifiedaccess_endpoint | endpoint_domain_prefix |
Security Group | aws_default_security_group | name_prefix |
Security Group | aws_security_group | name_prefix |
Pull Through Cache Rule | aws_ecr_pull_through_cache_rule | ecr_repository_prefix |
Cluster | aws_ecs_cluster | s3_key_prefix |
Identity Provider Config | aws_eks_identity_provider_config | groups_prefix |
Node Group | aws_eks_node_group | node_group_name_prefix |
Environment | aws_elastic_beanstalk_environment | cname_prefix |
Classic Load Balancer | aws_elb | bucket_prefix |
Load Balancer | aws_alb | name_prefix |
Target Group | aws_alb_target_group | name_prefix |
Trust Store | aws_lb_trust_store | name_prefix |
Security Configuration | aws_emr_security_configuration | name_prefix |
Job Template | aws_emrcontainers_job_template | log_stream_name_prefix |
Rule | aws_cloudwatch_event_rule | name_prefix |
Delivery Stream | aws_kinesis_firehose_delivery_stream | s3_error_output_prefix |
Accelerator | aws_globalaccelerator_accelerator | flow_logs_s3_prefix |
Custom Routing Accelerator | aws_globalaccelerator_custom_routing_accelerator | flow_logs_s3_prefix |
Crawler | aws_glue_crawler | table_prefix |
Group Policy | aws_iam_group_policy | name_prefix |
Instance Profile | aws_iam_instance_profile | name_prefix |
Policy | aws_iam_policy | name_prefix |
Role | aws_iam_role | name_prefix |
Role Policy | aws_iam_role_policy | name_prefix |
Server Certificate | aws_iam_server_certificate | name_prefix |
User Policy | aws_iam_user_policy | name_prefix |
User | aws_identitystore_user | honorific_prefix |
Distribution Configuration | aws_imagebuilder_distribution_configuration | s3_prefix |
Infrastructure Configuration | aws_imagebuilder_infrastructure_configuration | s3_key_prefix |
Monitor | aws_internetmonitor_monitor | bucket_prefix |
Topic Rule | aws_iot_topic_rule | execution_name_prefix |
Data Source | aws_kendra_data_source | s3_prefix |
Application | aws_kinesis_analytics_application | name_prefix |
Application | aws_kinesisanalyticsv2_application | name_prefix |
Alias | aws_kms_alias | name_prefix |
Permission | aws_lambda_permission | statement_id_prefix |
Log Group | aws_cloudwatch_log_group | name_prefix |
Classification Export Configuration | aws_macie2_classification_export_configuration | key_prefix |
Classification Job | aws_macie2_classification_job | name_prefix |
Custom Data Identifier | aws_macie2_custom_data_identifier | name_prefix |
Findings Filter | aws_macie2_findings_filter | name_prefix |
ACL | aws_memorydb_acl | name_prefix |
Cluster | aws_memorydb_cluster | name_prefix |
Parameter Group | aws_memorydb_parameter_group | name_prefix |
Snapshot | aws_memorydb_snapshot | name_prefix |
Subnet Group | aws_memorydb_subnet_group | name_prefix |
Cluster | aws_neptune_cluster | cluster_identifier_prefix |
Cluster Instance | aws_neptune_cluster_instance | identifier_prefix |
Cluster Parameter Group | aws_neptune_cluster_parameter_group | name_prefix |
Event Subscription | aws_neptune_event_subscription | name_prefix |
Parameter Group | aws_neptune_parameter_group | name_prefix |
Subnet Group | aws_neptune_subnet_group | name_prefix |
App | aws_pinpoint_app | name_prefix |
Pipe | aws_pipes_pipe | name_prefix |
Cluster | aws_rds_cluster | cluster_identifier_prefix |
Cluster Instance | aws_rds_cluster_instance | identifier_prefix |
Cluster Parameter Group | aws_rds_cluster_parameter_group | name_prefix |
Custom DB Engine Version | aws_rds_custom_db_engine_version | database_installation_files_s3_prefix |
Event Subscription | aws_db_event_subscription | name_prefix |
DB Instance | aws_db_instance | identifier_prefix |
DB Option Group | aws_db_option_group | name_prefix |
DB Parameter Group | aws_db_parameter_group | name_prefix |
DB Subnet Group | aws_db_subnet_group | name_prefix |
Cluster | aws_redshift_cluster | s3_key_prefix |
Snapshot Schedule | aws_redshift_snapshot_schedule | identifier_prefix |
Bucket | aws_s3_bucket | bucket_prefix |
Bucket Logging | aws_s3_bucket_logging | partitioned_prefix |
Bucket Notification | aws_s3_bucket_notification | filter_prefix |
Endpoint Configuration | aws_sagemaker_endpoint_configuration | name_prefix |
Schedule | aws_scheduler_schedule | name_prefix |
Schedule Group | aws_scheduler_schedule_group | name_prefix |
Secret | aws_secretsmanager_secret | name_prefix |
Receipt Rule | aws_ses_receipt_rule | object_key_prefix |
State Machine | aws_sfn_state_machine | name_prefix |
Signing Profile | aws_signer_signing_profile | name_prefix |
Signing Profile Permission | aws_signer_signing_profile_permission | statement_id_prefix |
Association | aws_ssm_association | s3_key_prefix |
Maintenance Window Task | aws_ssm_maintenance_window_task | output_s3_key_prefix |
Domain | aws_swf_domain | name_prefix |
Table | aws_timestreamwrite_table | object_key_prefix |
Rule Group | aws_wafv2_rule_group | name_prefix |