CloudFormation
02 / 02

Stacks, Changesets, Intrinsic Functions & Best Practices

CloudFormation: Stacks, Changesets & Best Practices

CLI: Stack Operations

# Deploy stack
aws cloudformation deploy   --template-file template.yaml   --stack-name my-app-dev   --parameter-overrides Environment=dev DbPassword=secret123   --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM   --region us-east-1

# Create stack (alternative — more control)
aws cloudformation create-stack   --stack-name my-app   --template-body file://template.yaml   --parameters ParameterKey=Environment,ParameterValue=dev   --capabilities CAPABILITY_IAM

# Update stack
aws cloudformation update-stack   --stack-name my-app   --template-body file://template.yaml   --parameters ParameterKey=Environment,ParameterValue=prod

# Wait for completion
aws cloudformation wait stack-create-complete --stack-name my-app
aws cloudformation wait stack-update-complete --stack-name my-app

# Describe stack
aws cloudformation describe-stacks --stack-name my-app
aws cloudformation describe-stack-events --stack-name my-app

# Delete stack
aws cloudformation delete-stack --stack-name my-app
aws cloudformation wait stack-delete-complete --stack-name my-app

# Validate template
aws cloudformation validate-template --template-body file://template.yaml

Changesets

Changesets let you preview what CloudFormation will do before executing. Always use changesets for production updates.

# Create changeset (preview changes)
aws cloudformation create-change-set   --stack-name my-app   --template-body file://template.yaml   --change-set-name my-update-$(date +%Y%m%d)   --parameters ParameterKey=InstanceType,ParameterValue=t3.small

# View changeset (what will be added/modified/removed)
aws cloudformation describe-change-set   --stack-name my-app   --change-set-name my-update-20240315

# Execute changeset
aws cloudformation execute-change-set   --stack-name my-app   --change-set-name my-update-20240315

# Delete changeset (if you decide not to apply)
aws cloudformation delete-change-set   --stack-name my-app   --change-set-name my-update-20240315

Intrinsic Functions

# !Ref — reference a parameter or resource
VpcId: !Ref MyVPC

# !Sub — string substitution
Name: !Sub '${AWS::StackName}-web-${Environment}'
# AWS pseudo-parameters: AWS::AccountId, AWS::Region, AWS::StackName, AWS::NoValue

# !GetAtt — get attribute of a resource
RoleArn: !GetAtt MyRole.Arn
BucketDomainName: !GetAtt MyBucket.DomainName

# !FindInMap — lookup in Mappings
ImageId: !FindInMap [RegionAMI, !Ref AWS::Region, AMI]

# !Select — pick item from list
AZ: !Select [0, !GetAZs '']  # first AZ in region

# !Split — split string to list
Parts: !Split [',', 'a,b,c']

# !Join — join list to string
BucketName: !Join ['-', [!Ref AWS::StackName, !Ref Environment, 'data']]

# !If — conditional value
MultiAZ: !If [IsProduction, true, false]
OptionalResource:
  Type: AWS::S3::Bucket
  Condition: IsProduction   # only create if condition is true

# !ImportValue — cross-stack reference
VpcId: !ImportValue 'network-stack-VpcId'

# !Base64 — encode for UserData
UserData: !Base64 |
  #!/bin/bash
  echo "Hello" > /tmp/test.txt

Best Practices

  • Use changeset review for all production updates — never update-stack directly in prod.

  • Set DeletionPolicy: Retain or Snapshot on stateful resources (RDS, S3) to prevent accidental loss.

  • Use nested stacks to split large templates: AWS::CloudFormation::Stack with TemplateURL.

  • Use StackSets to deploy the same template across multiple accounts and regions simultaneously.

  • Store sensitive parameters in AWS Secrets Manager or SSM Parameter Store (SecureString), not template Parameters.

  • Tag all resources consistently: add a Tags section to every resource for cost allocation and filtering.

  • Use cfn-lint (CloudFormation Linter) in CI to catch errors before deployment.

  • Prefer CDK or SAM for complex applications — they generate CloudFormation but with better abstractions.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free