# Infrastructure as Code with AWS CloudFormation

> Chapter 2 of the Courseiva AWS-DEVOPS-PROFESSIONAL curriculum — https://courseiva.com/learn/aws-devops-professional/infrastructure-as-code-with-cloudformation

**Official objective:** 2.1 — Implement CloudFormation templates and stack management

## Introduction

How do you build and manage hundreds of cloud servers, databases, and security rules without forgetting one single setting or introducing manual errors? That is the exact problem Infrastructure as Code solves, and it is a core skill tested in the DOP-C02 exam. In plain terms, Infrastructure as Code (IaC) means you write and store the configuration of your entire cloud environment as code files, which you can review, share, re-run, and change safely, just like your application code.

## The House-Building Architect Analogy

Have you ever watched someone build a house entirely by memory, only to realise later that the kitchen window faces a brick wall? That is what managing cloud infrastructure without Infrastructure as Code feels like.

Imagine you are an architect designing a house. You could walk onto a construction site and shout directions to the builders: 'Put a door here! Add a window there! Paint this wall blue!' But if you get distracted, leave for an hour, or try to explain it differently to a second builder, chaos erupts. The doors end up in the wrong rooms, the paint is mismatched, and nobody knows who changed what.

Now imagine instead, you write a single, detailed blueprint. That blueprint says: 'Front door is exactly 1 metre wide, positioned 3 metres from the left corner. The kitchen has two south-facing windows of 1.2 metres each. The living room walls are painted #F5F5DC.' You hand this blueprint to the builders, and they follow it precisely. If you want to change something, you edit the blueprint, not shout new orders. The blueprint is your source of truth, repeatable, version-controlled, and un-misunderstandable.

In cloud computing, AWS CloudFormation is that blueprint for your entire digital house — servers, databases, networks, security rules — all defined in a template file. You never click buttons in a console again. You write the template, and AWS builds exactly what you specified, every single time, without mistakes.

## Core explanation

Infrastructure as Code (IaC) is a way to manage and provision cloud resources through machine-readable definition files, rather than using a web console (pointing and clicking) or running manual commands one-by-one. AWS CloudFormation is Amazon's native IaC service that lets you describe exactly what you want — servers (EC2 instances), databases (RDS), networks (VPCs), security groups, load balancers — in a single file called a template.

Before IaC, IT teams would log into the AWS Console, click around to launch a server, configure its size, pick an operating system, set up networking, and then repeat that process for every single new server. This manual approach is slow, error-prone (one wrong checkbox can expose data to the internet), and impossible to reproduce consistently. If a server broke and you needed an identical replacement, you would have to remember every setting you chose, hoping you did not miss one.

CloudFormation replaces this by using what is called a 'declarative' approach. Declarative means you simply declare the final state you want — for example: 'I want one t2.micro EC2 instance, with 20 GB of gp2 storage, in the us-east-1a availability zone, behind a load balancer, with security group allowing HTTPS only.' You do not tell AWS the step-by-step commands to achieve it (that would be 'imperative'). Instead, CloudFormation figures out the order and dependencies automatically.

A CloudFormation template is a text file written in JSON or YAML format. YAML is more human-readable and is the preferred format for most DevOps engineers. The template has several major sections:

- AWSTemplateFormatVersion: declares which version of the template language you are using (usually '2010-09-09').
- Description: a free-text field explaining what the template does.
- Parameters: where you define inputs that the user can provide when launching the stack (like instance size or environment name). This makes templates reusable across different environments (dev, test, production).
- Mappings: a static lookup table, like mapping AWS region names to their corresponding Amazon Machine Image (AMI) IDs.
- Conditions: logic that determines whether certain resources should be created, for example, 'Create a larger database only if the environment is production'.
- Resources: the most important section. Here you define every AWS resource you want to create. Each resource has a logical name (like 'MyWebServer') and a Type (like 'AWS::EC2::Instance'), plus properties specific to that resource type.
- Outputs: information you want to return after the stack is created, such as the public IP address of the new web server.

When you submit a template to CloudFormation, it creates something called a 'stack'. A stack is a collection of AWS resources that you manage as a single unit. If you need to delete everything, you delete the stack, and CloudFormation removes all resources in the correct order. This is a massive safety improvement over manually deleting each component and risking leaving behind orphaned storage or security groups.

One critical concept is 'stack updates'. When your requirements change, you modify the template and run a stack update. CloudFormation analyses the differences between the current stack and the new template, and then makes only the necessary changes — adding, removing, or modifying resources — while leaving everything else untouched. It uses something called a 'change set' to show you exactly what will change before you commit.\

Another essential feature is 'stack sets', which let you deploy a single template across multiple AWS accounts and regions from one central location. For example, a company might want to enforce the same security rules (like encryption at rest) across every account in every region. A stack set does that in one operation.

CloudFormation also integrates with 'AWS CloudFormation Designer', a visual tool that helps you sketch out your architecture and generate templates, though most professionals write templates by hand using a code editor. Because the template is just a text file, you store it in a version control system like Git. This gives you a complete history of every change to your infrastructure, who made it, and why — something impossible with manual clicking.

Finally, CloudFormation is not the only IaC tool — alternatives include Terraform (from HashiCorp) and AWS CDK (Cloud Development Kit). The DOP-C02 exam focuses specifically on CloudFormation, so you need to master its syntax, update strategies, and troubleshooting patterns.

## Real-world context

Picture this: you work for a growing e-commerce company called 'ShopStream'. The company runs its payment processing system on AWS. Currently, the infrastructure was set up manually by a senior engineer who left the company six months ago. No one knows exactly how all the pieces connect. This week, an audit reveals that the payment database is not encrypted, which violates PCI compliance standards.

Your manager asks you to fix it. Without IaC, your day goes like this:

- You log into the AWS Console and find the database instance ID by guessing from a list of twenty similar-looking names.
- You click 'Modify' and enable encryption, but the console warns that encryption can only be enabled during creation, not modification. So you must create a new encrypted database, migrate the data manually, update the application's connection string, and delete the old database — a high-risk, multi-step process with many opportunities for error.
- You document the steps in a Word document, which will be outdated within a week.

If instead, the infrastructure was managed with CloudFormation, your day looks completely different:

- You find the existing CloudFormation template stored in the company's Git repository. You open it in your editor.
- You locate the 'AWS::RDS::DBInstance' resource and add the line: StorageEncrypted: true.
- You also notice the template uses an 'AWS::EC2::SecurityGroup' with a rule that allows SSH (port 22) from anywhere (0.0.0.0/0). That is a security risk. You change the CIDR IP to your office's static IP.
- You commit the change to a new Git branch, open a pull request, and your colleague reviews the diff (the changes). They spot a typo: you wrote 'StorageEncrypted: treu' instead of 'true'. They fix it before it ever touches production.
- After approval, you run 'aws cloudformation update-stack' from the command line. CloudFormation generates a change set showing two changes: the database will be replaced with an encrypted one, and the security group rule will be updated. No other resources are affected.
- You apply the change set. CloudFormation handles the database replacement, data migration, and security update in the correct order, automatically.
- After completion, you tag your Git commit with the version number.

In this scenario, the company benefits from version control (you know who changed what), code review (catching errors before deployment), automation (no manual clicking), and consistency (the template can be used to rebuild the entire environment in a disaster recovery situation within minutes).

The DOP-C02 exam expects you to understand this workflow in detail. You will be asked about how to propagate changes across stacks, how to handle dependencies between resources, and what happens when a stack update fails (rollback behaviour).

## Exam focus

The DOP-C02 exam tests your ability to design, implement, and troubleshoot CloudFormation templates and stack management. You will not be asked to write a full template from scratch, but you will need to interpret template snippets and predict the outcome of changes.

Key exam topics include:

- Resource dependencies: CloudFormation automatically determines the order of creation based on the Ref and DependsOn attributes. Exam questions often present a template and ask: 'Which resource is created first?' or 'What happens if resource A depends on resource B, but B fails?'
- Change sets: You must know the difference between direct stack updates and generating a change set to review before applying. A common question: 'A company wants to review the impact of a change before implementing it. Which feature should they use?' The answer is 'Change sets'.
- Stack updates: Know the four update behaviours: Update with No Interruption, Update with Some Interruption, Update by Replacement, and Update with Replacement (where CloudFormation creates a new resource and deletes the old one). The exam tests which behaviour applies to specific resource property changes. For example, changing the instance type of an EC2 instance triggers a replacement (stop and start), which causes downtime.
- Nested stacks: A single stack can reference other templates as nested stacks. This is useful for reusing common components like a VPC base. The exam asks about limits (maximum number of nested stacks) and output passing between parent and child stacks.
- Stack sets: Know that StackSets allow you to deploy stacks across multiple accounts and regions from a single template. A typical question: 'A company has 50 accounts and wants to enforce the same encryption policy in all regions. Which service should they use?' Answer: CloudFormation StackSets.
- Drift detection: Over time, people might manually change a resource (like resizing a database in the console). Drift detection compares the current state of the stack to the template and reports differences. The exam tests your ability to identify when drift has occurred and how to remediate it (by updating the stack or updating the template).
- Termination protection: By default, deleting a stack deletes all its resources. Termination protection prevents accidental deletion of critical stacks. A classic exam trap: 'A developer cannot delete a stack. What is the likely cause?' The answer is termination protection is enabled.
- Stack policies: These are JSON documents that define which resources in a stack can be updated or deleted during a stack update. They protect critical resources like production databases from accidental modification.
- Intrinsic functions: You must understand functions like Ref, Fn::GetAtt, Fn::Join, Fn::Select, and Fn::Sub. Questions often present a YAML snippet using one of these functions and ask what value it returns or what it does.

Common exam traps:

- Confusing 'Parameters' (user-provided values at launch) with 'Mappings' (hardcoded lookup tables).
- Assuming that all resource properties can be changed without replacement. Many exam questions intentionally describe a change that requires a full resource replacement, causing downtime. The correct answer often acknowledges the downtime and suggests a strategy to minimise it.
- Forgetting that CloudFormation requires an IAM role to create resources, or that resource creation might fail because of service quotas or permissions.
- Mixing up 'UpdateStack' and 'CreateStack' API calls. The exam expects you to know which operation to use when you are modifying an existing infrastructure.

Memorise this pattern: When a new version of a template is submitted for an existing stack, CloudFormation performs an 'UpdateStack' operation, which compares the new template to the current template and calculates the minimal set of changes needed. If you want to see the changes without applying them, you use 'CreateChangeSet' and then 'ExecuteChangeSet'.

## Step by step

1. **1. Define the Template Structure** — Create a new file with a .yaml or .json extension. Start with the AWSTemplateFormatVersion (always '2010-09-09') and an optional Description. Then define Parameters, Mappings, Conditions, Resources, and Outputs. The Resources section is mandatory — at least one resource must be defined.
2. **2. Add Resource Definitions** — For each AWS resource you need (like an EC2 instance, RDS database, or S3 bucket), write a logical name (e.g., 'MyWebServer') and a resource type (e.g., 'AWS::EC2::Instance'). Add properties such as ImageId, InstanceType, SecurityGroups, etc. Use the Ref and Fn::GetAtt intrinsic functions to reference other resources within the template.
3. **3. Validate the Template** — Use the AWS CLI command 'aws cloudformation validate-template' or the 'Validate Template' button in the AWS console. This checks for syntax errors, missing required properties, and valid resource types. Fix any errors before proceeding.
4. **4. Create the Stack** — Run 'aws cloudformation create-stack' with the template file URL or the inline template. CloudFormation then creates the stack and all defined resources. You can monitor the progress in the CloudFormation console. The stack status will change from CREATE_IN_PROGRESS to CREATE_COMPLETE or CREATE_FAILED.
5. **5. Update the Stack When Requirements Change** — When your infrastructure needs change, edit the template file. Use 'aws cloudformation create-change-set' to generate a change set that lists exactly what will be added, modified, or replaced. Review it, then run 'aws cloudformation execute-change-set' to apply the changes. CloudFormation handles dependencies and minimises downtime.
6. **6. Delete the Stack When No Longer Needed** — To remove all resources created by the stack, run 'aws cloudformation delete-stack'. By default, CloudFormation deletes every resource it created. If you want to retain specific resources (like an S3 bucket with data), set the 'DeletionPolicy' attribute to 'Retain' in the template before deletion.

## Comparisons

### CloudFormation vs Manual AWS Console

**CloudFormation:**
- All infrastructure defined in a version-controlled text file
- Supports drift detection to identify unauthorised changes
- Stack updates are automated and can include rollback on failure

**Manual AWS Console:**
- Infrastructure state lives only in the engineer's memory or documentation
- No automatic drift detection; manual audit required
- Changes are implemented by clicking buttons one at a time, prone to error

### Nested Stacks vs Cross-Stack References

**Nested Stacks:**
- One template includes another template as a resource within the same stack
- Used for reusing common components like VPC or security group templates
- Parent stack manages the lifecycle of all nested stacks together

**Cross-Stack References:**
- Separate stacks share values using Fn::ImportValue from stack outputs
- Used for sharing resource identifiers like VPC ID or database endpoint
- Each stack is managed independently; deletion order must be manual

### Stack Update with Change Set vs Stack Update Without Change Set

**Stack Update with Change Set:**
- Generates a detailed list of changes before applying them
- Requires an additional step (create then execute)
- Recommended for production environments to avoid surprises

**Stack Update Without Change Set:**
- Changes are applied immediately when update-stack is called
- Single step process, faster for development
- No preview; potential for unintended modifications

### DeletionPolicy: Retain vs Default Deletion (Delete)

**DeletionPolicy: Retain:**
- Preserves the resource even when the stack is deleted
- Useful for databases, S3 buckets with important data
- Resource becomes orphaned and must be managed outside CloudFormation

**Default Deletion (Delete):**
- Every resource created by the stack is deleted when the stack is deleted
- Ensures clean state and avoids hidden ongoing costs
- Requires careful consideration for stateful resources

### Parameters vs Mappings

**Parameters:**
- Input values provided by the user when launching or updating a stack
- Allow template reusability across environments (e.g., different instance sizes)
- Values can be referenced using Ref function

**Mappings:**
- Static lookup tables defined inside the template
- Used for region-specific values like AMI IDs or availability zones
- Values are referenced using Fn::FindInMap function

## Diagram

_This diagram illustrates the lifecycle of a CloudFormation stack from template creation through updates and deletion._

```mermaid
flowchart TD
    A[Designer writes YAML/JSON template] --> B[Validate template locally or via AWS CLI]
    B --> C[Create Stack or Change Set]
    C --> D[CloudFormation Engine calculates dependencies]
    D --> E[Creates resources in correct order]
    E --> F[Stack status: CREATE_COMPLETE]
    F --> G[Monitor stack via AWS Console or CLI]
    G --> H[Update template for changes]
    H --> I[Generate Change Set]
    I --> J[Review proposed changes]
    J --> K[Execute Change Set]
    K --> L[Update complete or rollback]
    L --> F
    F --> M[Delete stack = delete all resources]
```

## Common misconceptions

- **Misconception:** CloudFormation templates are executed like a script in order, so the first resource defined in the template is always created first. **Reality:** CloudFormation automatically resolves dependencies and creates resources in the correct order — not the order they appear in the template. You can use the DependsOn attribute to explicitly override the automatic order if needed. (People familiar with procedural programming assume that the order of lines in a file defines execution order. CloudFormation is declarative, so it analyses the entire template to determine dependencies.)
- **Misconception:** If I delete a CloudFormation stack, the resources inside it are never actually deleted; they just become orphaned. **Reality:** By default, deleting a CloudFormation stack deletes all the resources that were created by the stack during stack creation. This includes EC2 instances, databases, S3 buckets (if not empty), etc. There is a feature called 'Retain' on a resource that prevents deletion, but you must explicitly set it. (Some beginners come from environments where manual deletion is required, and they underestimate the power of CloudFormation's automated lifecycle management.)
- **Misconception:** CloudFormation templates can only be written in JSON, because YAML is not supported. **Reality:** CloudFormation supports both JSON and YAML formats. YAML is often preferred because it is cleaner and more readable for complex templates. The DOP-C02 exam tests both formats. (Many older online tutorials were written before YAML support was added, and some learners assume YAML is only for Terraform.)
- **Misconception:** Once a stack is created, you cannot change the template — you must delete the stack and recreate it. **Reality:** You can use the UpdateStack operation to modify an existing stack. CloudFormation calculates the difference between the existing stack and the new template, and applies only the necessary changes. This is one of the most powerful features of CloudFormation. (This misconception comes from beginners confusing CloudFormation with an immutable infrastructure tool, when in fact it supports both creation and incremental updates.)
- **Misconception:** Nested stacks and cross-stack references are the same thing and can be used interchangeably. **Reality:** Nested stacks are when one template includes another template as a resource within the same stack. Cross-stack references use the Fn::ImportValue function to share outputs between completely separate stacks. They are different mechanisms with different use cases and limitations. (The names sound similar and both involve multiple templates, so new learners mix them up. The exam tests the distinction.)

## Key takeaways

- CloudFormation is a declarative Infrastructure as Code service that lets you define all AWS resources in a single template file, eliminating manual errors and enabling repeatable deployments.
- A CloudFormation stack is a collection of AWS resources managed as a single unit; deleting the stack removes all its resources by default.
- Stack updates use change sets to preview the impact of modifications before applying them, which is critical for production environments.
- StackSets allow you to deploy identical stacks across multiple AWS accounts and regions from a single template, ensuring consistency at scale.
- Drift detection compares the actual state of resources to the template definition, revealing unauthorised manual changes.
- Intrinsic functions like Ref, Fn::GetAtt, Fn::Join, and Fn::Sub are essential for creating dynamic and reusable templates.
- Termination protection prevents accidental deletion of critical stacks by adding a layer of confirmation before deletion.
- CloudFormation templates are stored as text files in Git, giving you full version control, code review, and audit trail for all infrastructure changes.

## FAQ

**What is the difference between a CloudFormation template and a stack?**

A template is the JSON or YAML file that defines your infrastructure resources. A stack is the live, running collection of resources created from that template. You can have multiple stacks from the same template (e.g., one for dev and one for production).

**Can I convert a manually created resource (like an EC2 instance launched from the console) into a CloudFormation stack?**

Not directly, but you can use 'AWS CloudFormer' or the 'Resource Import' feature (stack import) to bring existing resources into an existing or new stack. You must create a template that matches the current configuration of the resource.

**What happens if a CloudFormation stack update fails?**

By default, CloudFormation performs a 'rollback on failure'. It automatically reverts all changes made during the update attempt, restoring the stack to its previous state. You can disable this behaviour with the 'DisableRollback' flag, but it is rarely recommended in production.

**How do I handle secrets like database passwords in CloudFormation templates?**

Never hardcode secrets in the template. Use the 'AWS Systems Manager Parameter Store' or 'AWS Secrets Manager' to store secrets, and reference them using the 'dynamic reference' syntax (e.g., '{{resolve:ssm:/myapp/dbpassword:1}}') in the template properties.

**Is CloudFormation free to use?**

Yes, AWS CloudFormation itself has no additional cost. You only pay for the underlying resources that CloudFormation creates (e.g., EC2 instances, RDS databases, storage).

**What is the maximum size of a CloudFormation template?**

The maximum template size is 512 KB for a template file, or 460 KB for a template URL. If your template is larger, you can break it into nested stacks or use template snippets stored in Amazon S3.

**Can I use CloudFormation with resources that are not part of AWS?**

CloudFormation is designed only for AWS resources. For multi-cloud or on-premises resources, you would use tools like Terraform or Pulumi. CloudFormation Registry does support third-party resource types via extensions, but it is primarily an AWS-native tool.

## Check your understanding

1. **What is the difference between a CloudFormation stack and a CloudFormation template?**

   Answer: A template is the YAML or JSON file that defines the desired infrastructure, while a stack is the live set of resources created and managed by CloudFormation from that template.

2. **You want to modify an existing stack but first review a list of all changes that will be made. Which CloudFormation feature should you use?**

   Answer: You should use a change set. Create a change set from the modified template, review the proposed changes, and then execute the change set to apply them.

3. **A company has 40 AWS accounts and wants to deploy identical security controls across all regions in all accounts. Which CloudFormation feature is the correct solution?**

   Answer: CloudFormation StackSets allows you to deploy a single template across multiple accounts and regions from one central management account.

4. **An engineer manually resized an RDS instance in the AWS Console, causing the CloudFormation stack to no longer match the template. What is this scenario called, and which CloudFormation action detects it?**

   Answer: This is called 'drift'. Drift detection compares the actual state of stack resources to the template and reports any differences.

5. **What is the purpose of the 'DependsOn' attribute in a CloudFormation resource definition?**

   Answer: DependsOn explicitly specifies that one resource must be created after another, overriding CloudFormation's default dependency inference. It is used when CloudFormation cannot automatically detect the dependency (e.g., a custom resource relying on a non-Ref relationship).

---

Interactive version with quiz and diagrams: https://courseiva.com/learn/aws-devops-professional/infrastructure-as-code-with-cloudformation
