**Approach (short)** I would centralize naming in a single module or shared vars + locals file, derive names from environment, account, team, resource type and a short identifier, and enforce with linting/policy checks in CI and pre-commit hooks so names are predictable and unique.**Example locals / naming templates**hcl
# modules/common/locals.tf
variable "env" { type = string } # e.g., "prod", "stg", "dev"
variable "account" { type = string } # e.g., "123456789012"
variable "team" { type = string } # e.g., "billing"
variable "component" { type = string } # e.g., "etl", "api"
variable "short_id" { type = string } # human or ticket id, e.g., "01"
locals {
name_parts = [
substr(var.env, 0, 3), # env short
substr(var.team, 0, 6), # team short
substr(var.component, 0, 6), # component short
var.short_id
]
normalized = [for p in local.name_parts : lower(replace(p, "/[^a-z0-9-]/", "-"))]
resource_name = join("-", compact(local.normalized))
s3_bucket_name = "${local.resource_name}-${var.account}" # ensure global uniqueness
iam_role_name = "${local.resource_name}-role"
}
Usage (module consumer):hcl
module "etl_bucket" {
source = "../modules/common"
env = var.env
account = var.account_id
team = "billing"
component = "etl"
short_id = "v2"
}
resource "aws_s3_bucket" "b" { bucket = module.etl_bucket.s3_bucket_name }
resource "aws_iam_role" "r" { name = module.etl_bucket.iam_role_name ... }
**Why this works**- Deterministic: same inputs → same name- Names include account to avoid global collisions (S3)- Shortening/normalization keeps within provider limits and character rules**Enforcement in CI / pre-commit**- pre-commit hook: terraform fmt + terraform validate + a small shell/python check to assert naming pattern (regex) in generated plan: - run `terraform plan -out=plan.tfplan && terraform show -json plan.tfplan | jq` to extract resource names and assert regex.- Policy as code: use Conftest (OPA) or Sentinel to assert: - S3 buckets match regex ^[a-z0-9-]+-[0-9]{12}$ - IAM roles include team and env segments - No hard-coded names (must reference module/local)- TFLint with custom rules for naming conventions- CI gate: fail build on naming policy violations; include clear error messages with expected template**Edge cases & best practices**- Reserve a stable short_id pattern (ticket, timestamp) for cross-deploy uniqueness- Document canonical var values in repo README- Add tests that generate plan for each env/account to catch collisions before applyThis pattern ensures consistent, unique, and enforceable names across environments, accounts and teams.