DEV Community

Tejas Shinkar
Tejas Shinkar

Posted on

AWS CloudFormation — Infrastructure as Code, Templates, Stacks & Change Sets

Part of my AWS learning journey — transitioning from Systems Engineer to Cloud/DevOps. CloudFormation is the foundation of infrastructure automation on AWS — the point where "clicking in the console" becomes "code that can be reviewed, versioned, and reproduced."


📋 Topics Covered

# Topic Type
1 What is IaC and Why It Exists Concept + Interview
2 IaC Benefits Concept
3 What is CloudFormation Concept + Interview
4 How CloudFormation Works in the Backend Concept + Interview
5 CloudFormation Template Structure — All Sections with Limits Concept + Lab
6 Template Section Plain-English Explanations Concept
7 Template vs Stack — The Distinction Concept + Interview
8 CloudFormation Building Blocks Concept + Cert
9 YAML Basics for CF Templates Concept + Lab
10 CF Parameters Concept + Lab
11 CF Rules Concept + Cert
12 CF Mappings Concept + Cert
13 CF Outputs Concept + Lab
14 CF Conditions Concept + Cert
15 CF Intrinsic Functions Concept + Cert
16 CF Service Roles Concept + Interview
17 CF Stack Policies and Deletion Policies Concept + Interview
18 CF Change Sets Concept + Lab
19 CF Stack Sets Concept + DevOps
20 Lab — Full Build-Up with Real Failures Lab
21 Interview Questions Interview
22 Assignment Practice

What is IaC and Why It Exists

Before IaC, infrastructure was managed manually — someone SSH'd into servers, clicked through console UIs, and hoped they remembered what they changed. When that person left, the knowledge went with them. When you needed three identical environments, you clicked through the console three times and hoped for no mistakes.

IaC (Infrastructure as Code) is the practice of defining and managing infrastructure through code or configuration files — so infrastructure can be created, changed, versioned, and reproduced automatically.

Instead of clicking "create EC2 instance" in the console, you write a file that says "I want an EC2 instance with these specs." You give that file to a tool. The tool creates the instance. The file goes into Git. Next time you need the same instance, you run the same file. Exact same infrastructure, zero manual steps.

The same principles that apply to application code now apply to infrastructure:

  • Version control — track every change with a commit message
  • Code review — a colleague reviews infrastructure changes before they're applied
  • CI/CD pipelines — infrastructure changes tested and deployed automatically
  • Reproducibility — the same template produces identical infrastructure every time
  • Documentation — the template is the documentation

IaC Benefits

Benefit What it means in practice
Reproducibility Same template in any region or account → identical infrastructure
Version control Every change tracked in Git — who changed what, when, and why
Auditability Full history of infrastructure changes — essential for compliance
Automation CI/CD pipelines deploy infrastructure changes without human intervention
Drift detection Compare actual infrastructure against the template — catch unauthorized manual changes
Disaster recovery Recreate entire infrastructure in a new region in minutes
Consistency Dev, staging, prod built from the same template — no more "works on staging, broken in prod"

What is CloudFormation

AWS CloudFormation is AWS's native IaC service. You write a template (YAML or JSON), upload it, and CloudFormation creates, updates, and manages all resources on your behalf.

Think of CloudFormation as a construction manager working from a blueprint. Your YAML/JSON template is the blueprint — it describes exactly how your AWS infrastructure should look. CloudFormation reads the blueprint, builds the infrastructure, and remembers what it built. When you change the blueprint, the construction manager doesn't demolish the entire building — they identify what changed and modify only the affected parts.

Why CloudFormation over clicking in the console:

  • Console clicks are not reproducible — the exact sequence is never recorded
  • Templates can be reviewed, approved, and audited
  • Same template creates identical infrastructure across dev/staging/prod
  • Changes can be previewed before applying via Change Sets
  • Automatic rollback if something goes wrong during deployment

How CloudFormation Works in the Backend

Understanding this makes troubleshooting CloudFormation failures significantly easier. This is the exact flow from class — represented as a numbered sequence.

The entire backend flow:

[1] Parse + Validate: Reads your YAML/JSON, checks for syntax errors, validates that resource types and properties are correct.

[2] Transform Expansion: Expands any transforms — SAM shorthand, Includes, Language Extensions, Modules — into full CloudFormation resource definitions.

[3] Pre-deployment Validation: Checks whether the requested resources and configuration make sense before deployment begins. Validates IAM permissions and quota limits.

[4] Build Dependency Graph (DAG): Determines resource dependencies — what depends on what and what needs to happen first. Independent resources are flagged for parallel execution. Dependent resources are ordered correctly.

[5] Compute Change Set: Compares the current AWS state (stored in CloudFormation's transactional state store) with the new template to determine exactly what needs to change — Add, Modify, Remove, Replace.

[6] Evaluate Hooks / Guardrails: Checks predefined organizational/security rules before making changes. Example: verifying every S3 bucket has encryption enabled before creation proceeds.

[7] Parallel Execution (by DAG topological order): Independent resources are created/updated simultaneously. Dependent resources follow the required order. For each resource: Resource Provider handles the actual Create/Update/Delete API call. Then → Stabilization Loop — CloudFormation polls until the resource reaches its required ready state. A successful API call doesn't mean the resource is ready. Stabilization can take 20–90 minutes for some resources (RDS, ElasticSearch, etc.).

[8] Success or Failure:

  • Success → State Committed: Everything reaches the desired state → stack becomes CREATE_COMPLETE or UPDATE_COMPLETE
  • Failure → Rollback: CloudFormation attempts to undo the changes in reverse DAG order → returns the stack toward its previous stable state

🎯 Why this matters for troubleshooting: When a stack gets stuck at CREATE_IN_PROGRESS, it's in the Stabilization Loop — waiting for a resource to become available. Check the Events tab — it shows which resource is waiting and why. When it fails, the error comes from the underlying AWS API call in the Resource Provider step.


CloudFormation Template Structure — All Sections with Limits

A CloudFormation template is a YAML or JSON file with the following structure. Every section has limits you should know for production and for the SAA-C03 exam.

AWSTemplateFormatVersion: "2010-09-09"   # optional, but always write it
Description: "..."                        # max 1024 bytes
Metadata: {}                              # console UI hints, cfn-init config
Parameters: {}                            # max 200
Rules: {}                                 # UNDER-USED — param validation logic
Mappings: {}                              # max 200 mappings, 200 attrs each
Conditions: {}                            # max 512
Transform: []                             # macro/SAM expansion
Resources: {}                             # REQUIRED — max 500
Outputs: {}                               # max 200
Enter fullscreen mode Exit fullscreen mode

Only Resources is required. Every other section is optional.


Template Section Plain-English Explanations

From class — the clearest way to remember what each section does:

Section Plain-English Question It Answers
AWSTemplateFormatVersion What template format?
Description What is this blueprint for?
Metadata Extra blueprint information
Parameters What choices should the person deploying provide?
Rules Are those choices valid?
Mappings Lookup table for predefined values
Conditions Should this part be built or not?
Transform Expand/process the blueprint
Resources ⭐ What actually needs to be built?
Outputs What useful information should I give back after construction?

Template vs Stack — The Distinction

Template: A YAML or JSON file — the blueprint. A text file. By itself, it creates nothing. Lives in Git, S3, or locally.

Stack: What CloudFormation creates when it executes a template. A group of AWS resources managed together as one unit. The stack tracks every resource it created, their state, and the template that generated them.

The same template creates multiple stacks:

webapp.yaml (one file in Git)
→ Stack: webapp-dev → dev resources in dev account
→ Stack: webapp-staging → staging resources in staging account
→ Stack: webapp-prod → prod resources in prod account

Three environments, identical configuration, zero manual effort.


CloudFormation Building Blocks

SAM (Serverless Application Model)

Shorthand syntax for serverless — Lambda, API Gateway, DynamoDB — written in a simplified form. The Transform: AWS::Serverless-2016-10-31 macro expands SAM into full CloudFormation at deploy time. Instead of 50 lines to define a Lambda with its role and log group, SAM lets you write 10.

Include

Pulls content from another template file into the current one — splits large templates into focused, maintainable files.

Language Extensions

Adds extra syntax features — native string operations, length functions, ToJsonString — reducing repetitive code and making templates more flexible.

Modules

Reusable infrastructure components used across multiple templates. Define a "standard VPC setup" once as a module — reference it in every team's template without repeating 200 lines.


YAML Basics for CF Templates

# Comment in YAML

key: value                  # String
number: 42                  # Integer
boolean: true               # Boolean
list:                       # List/Array
  - item1
  - item2
nested:                     # Nested object/map
  key1: value1
  key2: value2
multiline: |                # Multi-line string (preserves newlines)
  line one
  line two
Enter fullscreen mode Exit fullscreen mode

Indentation is everything in YAML. Unlike JSON (curly braces), YAML uses 2-space indentation to show nesting. One wrong indent fails the entire template.


CF Parameters

Parameters let you avoid hardcoding values — instead the person deploying provides them at stack creation or update time.

The same template creates a t3.micro in dev and a c5.2xlarge in prod — just by passing different values. No template changes needed.

Parameters:
  InstanceType:
    Type: String
    Default: t3.micro
    AllowedValues:
      - t3.micro
      - t3.small
      - t3.medium
      - t3.large
    Description: "EC2 instance type for the web server"

  Environment:
    Type: String
    AllowedValues:
      - dev
      - staging
      - prod
    Description: "Deployment environment"
Enter fullscreen mode Exit fullscreen mode

Parameter types:

Type Use for
String Text values, names, identifiers
Number Numeric values
CommaDelimitedList Multiple strings
AWS::EC2::KeyPair::KeyName Validates the key pair exists before deploy
AWS::EC2::VPC::Id Validates the VPC ID exists before deploy
AWS::EC2::Subnet::Id Validates the subnet ID exists before deploy
AWS::SSM::Parameter::Value<String> Pulls value directly from SSM Parameter Store

🎯 Interview tip: AWS-specific parameter types (like AWS::EC2::VPC::Id) are validated before the stack starts deploying — an invalid VPC ID gets rejected immediately, not halfway through.

Limit: max 200 parameters per template.


CF Rules

Rules are the validation layer for Parameters — they ensure parameter combinations are valid, going beyond what AllowedValues alone can check.

AllowedValues can restrict a single parameter to a fixed list. But what if you need: "when Environment is prod, InstanceType must not be t3.micro"? That cross-parameter logic is what Rules handle.

Rules:
  ProdRequiresLargeInstance:
    Assertions:
      - Assert:
          !Or
            - !Not [!Equals [!Ref Environment, prod]]
            - !Not [!Equals [!Ref InstanceType, t3.micro]]
        AssertDescription: "Production environment cannot use t3.micro"
Enter fullscreen mode Exit fullscreen mode

🎯 Note from class: Rules are marked as "UNDER-USED" in practice — most teams use Parameters with AllowedValues for simple validation and rely on Conditions for conditional resource creation. But Rules are the correct tool when you need to validate that multiple parameter values make sense together.


CF Mappings

Mappings are lookup tables baked into your template. The classic use case — AMI IDs per region, so the person deploying doesn't need to know them.

Mappings:
  RegionAMIMap:
    ap-south-1:
      AMI: ami-0abcdef1234567890
    us-east-1:
      AMI: ami-0987654321fedcba
    eu-west-1:
      AMI: ami-0a1b2c3d4e5f67890

Resources:
  MyEC2:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !FindInMap [RegionAMIMap, !Ref AWS::Region, AMI]
Enter fullscreen mode Exit fullscreen mode

When deployed in Mumbai → uses Mumbai AMI automatically. The deployer doesn't touch AMI IDs.

Other uses: environment-specific instance sizes (prod gets t3.large, dev gets t3.micro), region-specific endpoint URLs.

Limit: max 200 mappings, 200 attributes each.


CF Outputs

Outputs are values CloudFormation surfaces after a stack is created — important resource identifiers made easy to find and reuse.

Outputs:
  BucketName:
    Description: "Name of the created S3 bucket"
    Value: !Ref MyBucket

  BucketARN:
    Description: "ARN of the S3 bucket"
    Value: !GetAtt MyBucket.Arn
    Export:
      Name: !Sub "${AWS::StackName}-BucketARN"
Enter fullscreen mode Exit fullscreen mode

Three uses:

  • Console visibility — after stack creation, Outputs appear in CloudFormation console. Easy to find the ALB DNS name or RDS endpoint without digging through service consoles.
  • Cross-stack references — one stack exports an Output, another imports it with Fn::ImportValue. Networking stack exports VPC ID → all application stacks import it.
  • Automation — scripts query Outputs to get resource identifiers dynamically.

Limit: max 200 outputs per template.


CF Conditions

Conditions add boolean logic — create resources or set property values only when certain conditions are true.

Parameters:
  Environment:
    Type: String
    AllowedValues: [dev, prod]

Conditions:
  IsProduction: !Equals [!Ref Environment, prod]

Resources:
  MyBucket:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: !If [IsProduction, Enabled, Suspended]

  ReadReplica:
    Type: AWS::RDS::DBInstance
    Condition: IsProduction    # Only created when IsProduction is true
    Properties:
      # read replica config...
Enter fullscreen mode Exit fullscreen mode

Condition functions:

Function What it does
!Equals [a, b] True if a equals b
!Not [condition] Inverts a condition
!And [c1, c2] True if both are true
!Or [c1, c2] True if either is true
!If [condition, true_value, false_value] Conditional value

Limit: max 512 conditions per template.


CF Intrinsic Functions

Built-in functions that build dynamic values, reference resources, and manipulate strings.

Function Short form What it does
Ref !Ref Default identifier of a resource or parameter value
Fn::GetAtt !GetAtt Specific attribute of a resource (ARN, DNS name, IP)
Fn::Sub !Sub String substitution — inserts variable values
Fn::Join !Join Joins a list with a delimiter
Fn::Select !Select Returns one item from a list by index
Fn::FindInMap !FindInMap Looks up a value in a Mappings table
Fn::If !If Returns one of two values based on a Condition
Fn::ImportValue Imports an Output exported by another stack
Fn::Base64 !Base64 Encodes string as Base64 (used for EC2 User Data)
Fn::Split !Split Splits a string into a list

!Ref vs !GetAtt — the key distinction:

!Ref MyBucket → bucket name (the default identifier for S3)
!GetAtt MyBucket.Arn → bucket ARN (a specific attribute)
!GetAtt MyInstance.PublicIp → public IP of EC2 (a specific attribute)

Practical example:

Resources:
  MyInstance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !Ref InstanceTypeParam          # value from Parameter
      ImageId: !FindInMap [AMIMap, !Ref AWS::Region, AMI]  # from Mappings
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-webserver"  # string substitution
      UserData:
        !Base64 |
          #!/bin/bash
          yum update -y
          yum install -y httpd
          systemctl start httpd

Outputs:
  PublicIP:
    Value: !GetAtt MyInstance.PublicIp
  FullDNS:
    Value: !Join [".", ["api", !Ref Environment, "tejascloud.com"]]
Enter fullscreen mode Exit fullscreen mode

CF Service Roles

By default, CloudFormation uses your own IAM permissions to create resources. A Service Role is an IAM Role that CloudFormation assumes instead — decoupling what humans can do from what CloudFormation can do.

Scenario: A developer needs to deploy a stack that creates VPCs, security groups, and EC2 instances. You could give the developer those IAM permissions directly — but then they could also manually create those resources outside CloudFormation, bypassing governance.

With a Service Role: The developer has cloudformation:CreateStack and iam:PassRole only. The Service Role has ec2:*, vpc:*, s3:* — whatever the stack needs. CloudFormation assumes the role and creates resources. The developer gets the infrastructure without direct access to the underlying services.

🎯 Security benefit: Least privilege for humans, necessary permissions for automation. Humans can't bypass the CloudFormation process to create resources manually.


CF Stack Policies and Deletion Policies

Stack Policy

A JSON document attached to a stack that controls which resources can be updated or replaced during a stack update.

{
  "Statement": [{
    "Effect": "Deny",
    "Action": "Update:Replace",
    "Principal": "*",
    "Resource": "LogicalResourceId/ProductionDatabase"
  }]
}
Enter fullscreen mode Exit fullscreen mode

This blocks Replace operations on the ProductionDatabase resource — even if a template change would normally require it. CloudFormation fails the update rather than replace the database.

Deletion Policy

Set on individual resources inside the template — controls what happens when the stack is deleted or the resource is removed from the template.

Deletion Policy What happens when stack is deleted
Delete (default) Resource is deleted
Retain Resource stays, CloudFormation stops managing it
Snapshot AWS takes a backup before deleting (RDS, EBS, Redshift)
Resources:
  MyDatabase:
    Type: AWS::RDS::DBInstance
    DeletionPolicy: Snapshot    # backup before delete
    Properties: {}

  MyBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain      # keep the bucket, just stop managing it
    Properties: {}
Enter fullscreen mode Exit fullscreen mode

🎯 Production rule: Always DeletionPolicy: Snapshot on RDS. Always DeletionPolicy: Retain on S3 buckets with important data. Losing a production database because of the default Delete policy is a real and painful mistake.


CF Change Sets

A Change Set is a preview of what CloudFormation will do before it actually does it — shows every resource action: Add, Modify, Remove, Replace.

A Replace action means the resource is deleted and recreated — downtime for databases, EC2 instances, etc. A Change Set lets you catch this before it happens.

The Change Set workflow:

Modify your YAML template → Upload new template → Create Change Set → CloudFormation computes the diff → Review every proposed change → If correct: Execute → CloudFormation applies → If risky or wrong: Delete the Change Set → nothing applied, stack untouched.

When to always use Change Sets: Before updating any production stack — catching a Replace before it runs is the difference between planned maintenance and an unplanned outage.


CF Stack Sets

Deploys the same CloudFormation stack across multiple AWS accounts and/or regions in a single operation.

Without Stack Sets: log into 10 accounts, switch to 3 regions in each, deploy 30 times manually.
With Stack Sets: define target accounts and regions once → CloudFormation deploys to all 30 in parallel.

Common uses: security baseline (CloudTrail, Config, GuardDuty) to every account, centralized logging in every region, standard networking across all accounts.

Two modes:

Mode How targets are defined
Self-managed You explicitly list account IDs and regions
Service-managed (AWS Organizations) Auto-deploys to all accounts in an OU — new accounts added to the OU automatically get the stack

Stack Instance = one deployed stack in one specific account + region combination.


🧪 Lab — Full Build-Up with Real Failures

This is the complete lab sequence from class — building a full networking + EC2 stack resource by resource using Change Sets. The failures are included because they're part of what makes CloudFormation real — and knowing how to fix them is the skill.

Overall Lab Flow

YAML Blueprint → Parameters → VPC → Subnet → Internet Gateway → Gateway Attachment → Route Table → Security Group → Key Pair Parameter → EC2 → Dependencies via !Ref → Change Sets → Execute → Failures → Fix Template/Parameter → New Change Set → Execute → Final Infrastructure ✅

Step-by-Step Lab — Exact Sequence

Start: Create VPC + CIDR

Create Stack → initial template with just VPC and CIDR → CREATE_COMPLETE

Add Subnet via Change Set

Modify template — add Subnet resource referencing VPC via !Ref → Create Change Set → Execute Change Set
FAILED: Invalid Availability Zone — AZ name in template was wrong
Fix AZ in template → Create New Change Set → Execute Change Set
Subnet Created ✅

Add Internet Gateway

Modify template — add AWS::EC2::InternetGateway, add AWS::EC2::VPCGatewayAttachment using !Ref VPC and !Ref IGW → Create Change Set → Execute
MyInternetGateway Created ✅
AttachGateway Created ✅
Internet Gateway Attached to VPC ✅

Add Route Table

Modify template — add AWS::EC2::RouteTable, add Route with destination 0.0.0.0/0 → IGW, add Subnet Route Table Association → Create Change Set → Execute
Route Table Created + Associated ✅

Add Security Group

Modify template — add AWS::EC2::SecurityGroup with inbound rules (SSH 22, HTTP 80) → Create Change Set → Execute
Security Group Created ✅

Add Key Pair as Parameter + Create EC2

Modify template — add KeyPair Parameter (Type: AWS::EC2::KeyPair::KeyName), add EC2 instance referencing AMI from Mappings, SG from !Ref, subnet from !Ref, key pair from !Ref KeyPairParam → Create Change Set → Execute
FAILED: Invalid/Non-existent Key Pair — wrong key pair name entered
Correct Key Pair Parameter → Create New Change Set → Execute Change Set
EC2 Created ✅

What the Lab Teaches

These failures are not bugs in the process — they're the lesson:

Invalid AZ failure: Template contained a hardcoded AZ that doesn't exist in the target region. Fix: use a Parameter for AZ name, or use !Select [0, !GetAZs !Ref AWS::Region] to dynamically pick the first available AZ.

Invalid Key Pair failure: AWS-specific parameter types (AWS::EC2::KeyPair::KeyName) validate that the key pair exists in the account — if you type a name that doesn't exist, it fails at parameter validation before any resource is created. Fix: enter the exact name of a key pair that exists in your account.

The Change Set → Execute → Fail → Fix → New Change Set → Execute cycle is normal production CloudFormation workflow. The key is that failures don't leave your infrastructure in an unknown state — CloudFormation's rollback mechanism returns you to the last stable state.

Final Template Structure (Everything Together)

AWSTemplateFormatVersion: "2010-09-09"
Description: "VPC + EC2 networking stack"

Parameters:
  KeyPairName:
    Type: AWS::EC2::KeyPair::KeyName
    Description: "Name of an existing EC2 key pair"

  AvailabilityZone:
    Type: AWS::EC2::AvailabilityZone::Name
    Description: "AZ to deploy the subnet in"

Mappings:
  RegionAMI:
    ap-south-1:
      AMI: ami-0f5ee92e2d63afc18
    us-east-1:
      AMI: ami-0abcdef1234567890

Resources:
  MyVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: "10.0.0.0/16"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-VPC"

  MySubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: "10.0.1.0/24"
      AvailabilityZone: !Ref AvailabilityZone
      MapPublicIpOnLaunch: true

  MyIGW:
    Type: AWS::EC2::InternetGateway

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref MyVPC
      InternetGatewayId: !Ref MyIGW

  MyRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC

  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId: !Ref MyRouteTable
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref MyIGW

  SubnetRouteTableAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref MySubnet
      RouteTableId: !Ref MyRouteTable

  MySecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "Allow SSH and HTTP"
      VpcId: !Ref MyVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: "0.0.0.0/0"
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: "0.0.0.0/0"

  MyEC2:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      KeyName: !Ref KeyPairName
      ImageId: !FindInMap [RegionAMI, !Ref AWS::Region, AMI]
      SubnetId: !Ref MySubnet
      SecurityGroupIds:
        - !Ref MySecurityGroup
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-WebServer"

Outputs:
  InstancePublicIP:
    Description: "Public IP of the EC2 instance"
    Value: !GetAtt MyEC2.PublicIp

  VPCID:
    Description: "VPC ID"
    Value: !Ref MyVPC
Enter fullscreen mode Exit fullscreen mode

Useful Pseudo Parameters

Available automatically — no declaration needed.

Pseudo Parameter Value
!Ref AWS::Region Current region (e.g., ap-south-1)
!Ref AWS::AccountId Current AWS account ID
!Ref AWS::StackName Name of the current stack
!Ref AWS::StackId Full ARN of the current stack
!Ref AWS::NoValue Removes a property (used in Conditions)

⚡ Quick Revision

IaC

  • Define infrastructure as code → version, review, reproduce, automate
  • Template is the blueprint. Stack is the deployed infrastructure.
  • Same template → multiple stacks → identical environments

Template Structure (with limits)

  • AWSTemplateFormatVersion → format version, always "2010-09-09"
  • Metadata → UI hints, cfn-init config
  • Parameters → max 200, user input at deploy time
  • Rules → cross-parameter validation logic (under-used but important)
  • Mappings → max 200 mappings × 200 attrs each, lookup tables
  • Conditions → max 512, boolean logic for conditional resources
  • Transform → SAM/macro expansion
  • Resources → REQUIRED, max 500, the actual AWS resources
  • Outputs → max 200, values surfaced after stack creation

CloudFormation Backend Flow

[1] Parse + Validate → [2] Transform Expansion → [3] Pre-deployment Validation → [4] Build DAG → [5] Compute Change Set → [6] Evaluate Hooks → [7] Parallel Execution (each resource: Resource Provider → API call → Stabilization Loop 20-90 min) → [8] Success: Commit State / Failure: Rollback in reverse DAG order

Key Intrinsic Functions

  • !Ref → default identifier (bucket name, instance ID, parameter value)
  • !GetAtt → specific attribute (ARN, DNS, public IP)
  • !Sub → string substitution with variables
  • !FindInMap → lookup value in Mappings table
  • !If → conditional value
  • !Base64 → encode string for User Data

Deletion Policy

  • Delete (default) → resource deleted with stack
  • Retain → resource stays, CloudFormation stops managing
  • Snapshot → backup before deletion (RDS, EBS)

Change Set

  • Preview before applying — shows Add, Modify, Remove, Replace
  • Replace = resource deleted and recreated = downtime
  • Always use before updating production stacks

Stack Sets

  • Same stack → multiple accounts/regions in one operation
  • Service-managed mode: auto-deploys to new accounts in an OU

💼 Interview Questions

Q1: What is the difference between a CloudFormation Template and a Stack?
A template is a YAML or JSON file — the blueprint that creates nothing by itself. A stack is what CloudFormation creates when it executes a template — a group of AWS resources managed together as one unit. The same template can create multiple stacks (dev, staging, prod), each independently managed.

Q2: How does CloudFormation handle resource dependencies?
CloudFormation builds a Directed Acyclic Graph (DAG) from DependsOn attributes, !Ref references, and !GetAtt calls. Resources with no dependencies are created in parallel. Dependent resources are created in the correct order. On failure, rollback follows the reverse DAG order.

Q3: What happens during the Stabilization Loop?
After making a Create/Update/Delete API call through a Resource Provider, CloudFormation doesn't assume the resource is immediately ready. It polls the resource until it reaches its required stable state. Some resources like RDS or Elasticsearch can take 20–90 minutes to stabilize. This is why CloudFormation stacks spend a long time in CREATE_IN_PROGRESS — they're waiting for stabilization, not making slow API calls.

Q4: What is a Change Set and why should you use one before updating a production stack?
A Change Set previews every change CloudFormation will make — which resources will be Added, Modified, Removed, or Replaced. A Replace action deletes and recreates a resource, causing downtime. Using a Change Set catches this before applying, preventing unplanned outages.

Q5: What is the difference between a Stack Policy and a Deletion Policy?
A Stack Policy is a JSON document attached to a stack that prevents specific resources from being updated or replaced during stack updates — protecting critical resources from accidental replacement. A Deletion Policy is a property on individual resources inside the template that controls what happens when the stack is deleted: Delete (remove), Retain (keep), or Snapshot (backup before deleting).

Q6: What is the difference between CF Parameters and CF Rules?
Parameters define the input values a deployer provides at stack creation or update. AllowedValues can restrict a single parameter to a fixed list. Rules are validation logic that works across multiple parameters — for example, "when Environment is prod, InstanceType must not be t3.micro." Parameters control individual inputs; Rules validate that combinations of inputs make sense together.

Q7: What is !Ref vs !GetAtt?
!Ref returns the default identifier of a resource — for S3 it returns the bucket name, for EC2 it returns the instance ID. !GetAtt returns a specific named attribute — !GetAtt MyBucket.Arn returns the ARN, !GetAtt MyInstance.PublicIp returns the public IP. Use !Ref for the primary identifier, !GetAtt for everything else.

Q8: What is a CloudFormation Service Role and why would you use it?
A Service Role is an IAM Role that CloudFormation assumes to create resources, instead of using the deploying user's permissions. It enforces governance — developers can deploy CloudFormation stacks without having direct IAM permissions to create EC2s or VPCs. CloudFormation assumes the role and creates resources, keeping least privilege for humans while enabling necessary automation.


📝 Assignment

Create a CloudFormation stack that deploys an Auto Scaling Group with a Launch Template and hosts a web server using a User Data script. The web server should be accessible via an Application Load Balancer. All resources created and managed by a single CloudFormation template.


AWS Session 16 — AWS CloudFormation | Cloud + DevOps learning journey — Systems Engineer → Cloud/DevOps Engineer

Top comments (0)