Skip to main content

Naming

Naming is one of the hard problems in computing. Naming instances in a shared name space, such as AWS, is especially rife with problems. Often a company uses a single AWS account across multiple projects and so the projects have to negotiate how to share the namespace for resources. There are a number of different axes of belonging we might want to include in the name: to which project does a resource belong, to which environment (dev, prod, staging), which function within the environment. Then there are entities which exist only in terms of their relationship to other objects, e.g. roles associated with a particular lambda function.

Things are further complicated in AWS because there are different uniqueness constraints in play:

Uniqueness constraintExample resources
Global (the entirety of AWS)S3 buckets
Per accountIAM resources (users, groups, roles, policies, …)
Per regionMost everything else (ALB, ECS, RDS, …)

As with all naming schemes (and other stylistic things such as casing and comments) where the client already has a functional naming scheme we should follow that - there are more important issues to deal with. However, for our own work and for projects where we are setting the standard we prefer to use the following.

Globally unique

S3 Buckets

If the AWS account is a monolithic account, this can require more complex naming conventions for bucket.

${account.alias}-${application.name}[-${environment}][-${region}] - these names begin with a consistent account/usage prefix as they are globally scoped across all of AWS.

  • $account-alias - is a prefix for the account, e.g. "truss", "client-name"
  • $application-name - is application for which the resource is created, e.g. "aws-logs", "webserver", "terraform-state"
  • $environment - can be used to distinguish different versions of the resource/app that occur during the development lifecycle, e.g. dev, perf_test, staging and production
  • $region - when an app can or will be distributed across AWS regions with distinct instances in each region, this postfix distinguishes between them

e.g.

  • truss-aws-logs-staging-us-east-1

If using AWS Organizations, ideally the ${account-alias} will include the ${environment}, which can result in more simple S3 naming convention.

${account.alias}-${application.name} - these names begin with a consistent account/usage prefix as they are globally scoped across all of AWS.

  • $account-alias - is a prefix for the account, e.g. "truss-dev", "spacecats-prod"
  • $application-name - is application for which the resource is created, e.g. "aws-logs", "webserver", "terraform-state"
  • [${region}] - optionally add the region if there are multiple regions used

e.g.

  • truss-dev-aws-logs
  • spacecats-prod-webserver

Unique per account

IAM resources

IAM resource names are account unique (i.e., visible across all regions), e.g. for roles:

${service/realm}[-${role}]-${project/application}-[${environment}] - is the general form

  • $service/realm - to what does this role pertain, e.g. "ecs", "lamda" or "circleci".
  • $role - where there may be multiple roles associated with a service, this can be used as a way of disambiguating, e.g "task-execution" or "rds-snapshot-cleaner"
  • $project/application - where there may be multiple applications/projects being managed with independent deploy cycles, this is used, e.g. "webapp", "honeycomb"
  • [$environment] - optionally can be used to distinguish different versions of the resource/app that occur during the development lifecycle, e.g. dev, perf_test, staging and production in monolithic AWS accounts

e.g.

  • lambda-rds-snapshot-cleaner-app-experimental
  • ecs-task-role-app-client-tls-experimental

IAM policies

Where the details of an IAM role are in an associated policy (usually the case) they are named after the associated role, but with -policy appended, e.g.

  • lambda-rds-snapshot-cleaner-app-experimental-policy
  • ecs-task-role-app-client-tls-experimental-policy

IAM users

When you create a new user, you should follow a first initial last name format (firstinitialLastName), e.g.

  • eeady for Elizabeth Eady
  • rkilberg for Rebecca Kilberg

Unique per region

Where the name is scoped by the resource type and the region, e.g. lambda functions, then it is enough to give a meaningful name and qualify by environment. If the purpose is common, e.g. rds-log-cleaner, it may need an application.

${purpose}[-${application}][-${environment}] - is the general form

  • $purpose - a simple name describing the role/purpose of the resource, e.g. "slack-bug-tracker-bot", "webserver", "rds-log-cleaner"
  • $application - if needed, disambiguates between a similar purpose across applications, e.g. "webapp" vs "honeycomb"
  • [$environment] - optionally can be used to distinguish different versions of the resource/app that occur during the development lifecycle, e.g. dev, perf_test, staging and production in monolithic AWS accounts

e.g.

  • slack-bug-tracker-bot-test
  • rds-log-cleaner-webapp-prod

SNS topics

The main purpose of the SNS topics are for notifications to teams. The naming convention reflects that, closely followed by the AWS account type (Gov or Com, if applicable) and action.

${team}[-${account_type}-]${action} - is the general form

Sample names:

  • app-com-notification
  • infra-gov-alert

Slackbot

When you are creating a bot in Slack to alert team members to issues, you should include team to alert and app name the alert is coming from.

  • {team}-${application}

e.g.

  • app-eclkc
  • hosting-ipd

VPC

VPCs are unique by region but they should indicate which application and environment level they contain.

${application}-[${environment}] - is the general form

  • $application - disambiguates between a similar purpose across applications, e.g. "webapp" vs "honeycomb"

  • [$environment] - optionally can be used to distinguish different versions of the resource/app that occur during the development lifecycle, e.g. dev, perf_test, staging and production in monolithic AWS accounts

e.g.

  • eec
  • eec-staging

Subnets

For non-db subnets: Although they are unique by region, we also want subnets to be descriptively named according to their AZs and public/private status.

${VPC name}-${public/private/db}-${AZ} - is the general form

  • $public/private/db - can be used to distinguish whether the subnet is a private, public, or db subnet
  • $AZ - Availability Zone (AZ) are within a region and are ordered initials (i.e. us-east-2b).

In a VPC named "eec-prod":

  • eec-prod-public-us-east-1a
  • eec-prod-private-us-west-2c

ECR

Elastic Container Repositories are unique by region within your account. They should be named according to the united principal of what they will contain. For example, if all the images in the repo will be related to a specific app team, then you can name the repo after the app team. If, on the other hand, they will all be images with variations of a set of software, you could name it after the software.

e.g.:

  • eclkc
  • php-nginx

Container images

Container images such as Docker or ECR images should include the date as a way to version. Although the convention is to name the latest version latest, this can become a sticky situation when folks are trying to refresh a build in terraform and they end up not pulling the latest because the name latest hasn't changed.

${date}-${application} - is the general form ${git commit hash}-${application} - for applications that build new images on main and therefore may have multiple images per day

  • $date - YYYY-MM-DD - disambiguates between other images for the same application
  • $git commit hash - disambiguates between other images for the same application taken on the same day
  • $application - disambiguates between a similar purpose across applications, e.g. "webapp" vs "honeycomb"

e.g. 2020-07-20-eclkc

Terraform modules

Typically when building resources and services in terraform, you will follow the naming conventions described above for AWS resources. However, when creating a standalone module, you should use the following convention, which is required to add the module to the Terraform registry.

terraform-${provider}-${purpose} - is the general form

  • $provider - the terraform provider, e.g. "aws", "pagerduty", "github"
  • $purpose - a simple name describing the role/purpose of the resource, e.g. "slack-bug-tracker-bot", "webserver", "rds-log-cleaner"

e.g.

  • terraform-aws-rds-log-cleaner
  • terraform-aws-cloudtrail-alarms