Introduction
AWS CloudFormation is a service that enables us to provision AWS and third-party resources by treating infrastructure as code. It allows us to have consistent and version-controlled deployments. While there are other popular tools for IaC like Terraform and Pulumi, CloudFormation is designed specifically for AWS resources and services. It uses YAML or JSON-based templates, which most users are already familiar with. Since it is AWS’s service for infrastructure as code, there are more official quickstarts provided by AWS, and AWS Support will be more capable of assisting when help is needed.
One of the benefits of using CloudFormation is that there is no state file that we have to manage. The deployments are represented within the CloudFormation service as a “stack”. Stack Events show the deployment results of the resources that were created/updated/deleted based on the provided template.
In this post, we’ll cover the basics of CloudFormation, including templates, stacks, change sets, and nested stacks, and explore how these features can simplify infrastructure management while giving us greater control and visibility over our deployments.
Key Concepts in CloudFormation
Template file
When it comes to template files, we have a choice between using JSON and YAML formats. YAML is clearer and easier to use, which is why it is often preferred. The basic structure of a YAML template file looks like this:
---
AWSTemplateFormatVersion: version date
Description:
String
Metadata:
template metadata
Parameters:
set of parameters
Rules:
set of rules
Mappings:
set of mappings
Conditions:
set of conditions
Transform:
set of transforms
Resources:
set of resources
Outputs:
set of outputs
Let’s walk through some of the most commonly used sections.
In the Resources section, we can declare the AWS resources that we want to have provisioned. It has the following structure:
Resources:
LogicalResourceName1:
Type: AWS::ServiceName::ResourceType
Properties:
PropertyName1: PropertyValue1
...
LogicalResourceName2:
Type: AWS::ServiceName::ResourceType
Properties:
PropertyName1: PropertyValue1
...
When creating resources, the following AWS Documentation comes in handy, as it gives information about all resource types and their properties: AWS CloudFormation Template Reference Guide
In the Parameters section, we can specify custom values for our parameters at runtime when we deploy the stack. If we are deploying it via the CloudFormation console, we will have a dropdown or an empty field in which we will be able to choose or write the value that we want. The only required attribute is Type.
Parameters:
ParameterLogicalID:
Description: Information about the parameter
Type: DataType
Default: value
AllowedValues:
- value1
- value2
When you have multiple stacks in the same AWS account and Region, you might want to share information between them. This is useful when one stack needs to use resources created by another stack.
To share information between stacks, we have to export output values from one stack and import them into another stack. The procedure is the following:
- In the first stack’s template, we define certain values for export by using the Export field in the Outputs section.
Outputs:
OutputLogicalID:
Description: Information about the value
Value: Value to return
Export:
Name: Name of resource to export
- Then we have to create/update that stack, so that the output value gets exported and available to other stacks. (In the CloudFormation console, we can see the output values for a given stack in the Outputs tab.)
- In the other stack’s template, we can then use the Fn::ImportValue function to import the exported values from the first stack.
- When we create/update the second stack, the exported value is automatically retrieved.
For a more thorough explanation of each of the sections, you can refer to the AWS documentation:
AWS CloudFormation template sections
Stacks
The CloudFormation stacks are logical groupings of AWS resources that are going to belong to a project. When you want to add, update, or delete resources in this resource group, you can do so by modifying the stack.
Creating a stack – this involves deploying a CloudFormation template that follows the structure and the syntax that we showed above. CloudFormation then provisions and configures the resources described in the template.
Updating a stack – this involves making changes to the template or the parameters. CloudFormation compares what you submit with the current state of the stack and updates only the changed resources. There are two methods for updating stacks – with Change sets (if you want a preview of the changes before deploying them) or via a Direct update. Direct update means that CloudFormation will immediately deploy the changes.
We cover Change sets in more detail later in this post.
Deleting a stack – this deletes all the resources associated with the stack.
Stack Status Codes
When working with stacks, you will have to follow the status code of your stack to know its state. It will tell you whether the change was successful, whether it failed and rolled back, whether the rollback was successful, etc.
To see more information about what was created, updated, or deleted, and if there are errors, you should choose your stack and go to the Events tab. There you will see the likely root cause of the failure, if the update wasn’t successful.
Here are a few common status codes and their meaning:
- CREATE_IN_PROGRESS – Ongoing creation of one or more stacks.
- CREATE_COMPLETE – Successful creation of one or more stacks.
- CREATE_FAILED – Unsuccessful creation of one or more stacks. You can see the reason for the failure in the Events tab.
- DELETE_IN_PROGRESS – Ongoing removal of one or more stacks.
- DELETE_COMPLETE – Successful deletion of one or more stacks. Deleted stacks are retained and viewable for 90 days.
- DELETE_FAILED – Unsuccessful deletion of one or more stacks. Some of the resources couldn’t be deleted. You can see why in the Events tab. You will have to manually delete them. (A possible reason can be if the resource has termination protection enabled.)
- UPDATE_IN_PROGRESS – Ongoing update of one or more stacks.
- UPDATE_COMPLETE – Successful update of one or more stacks.
- UPDATE_COMPLETE_CLEANUP_IN_PROGRESS – Ongoing removal of old resources for one or more stacks after a successful stack update. For stack updates that require resources to be replaced, CloudFormation creates the new resources first and then deletes the old resources to help reduce any interruptions with your stack. In this state, the stack has been updated and is usable, but CloudFormation is still deleting the old resources.
- UPDATE_ROLLBACK_IN_PROGRESS – Ongoing return of one or more stacks to the previous working state after a failed stack update. You can’t update the stack if it is in this state.
- UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS – Ongoing removal of new resources for one or more stacks after a failed stack update. In this state, the stack has been rolled back to its previous working state and is usable, but CloudFormation is still deleting any new resources it created during the stack update.
- UPDATE_ROLLBACK_COMPLETE – Successful return of one or more stacks to a previous working state after a failed stack update.
- UPDATE_ROLLBACK_FAILED – Unsuccessful return of one or more stacks to a previous working state after a failed stack update. You can’t update the stack while it is in this condition. Your options are to delete the stack or to continue rolling back. To continue the rollback, you have to go to your stack, click on Stack actions, and choose Continue update rollback. In the Additional information section, you will see which are the problematic resources, and you can mark them to be skipped. Then the rollback will finish successfully, and you will have to manually go and fix the failed resource. If you don’t want to perform any of these, you can contact Support to restore the stack to a usable state.
You can find information about all stack status codes in the following AWS documentation:
View CloudFormation stack events
Change Sets
Change sets help you see what exactly will be updated after you make a certain change. They show you the execution plan.
After you make a change to your template, you can go to the CloudFormation console, click on your stack, go to the Change sets tab, and create a change set. You will be asked to provide a template either from your local filesystem or from S3.

Then, similar to when you create a stack, you will be asked to give value to the parameters and an IAM role that the stack will use to create or update the resources.


After you create the change set, you will be able to see the differences between your current template and your new one, and make sure it is exactly what you want to change before executing the change set. It also gives you information on whether the resource will be replaced or not.


When you are ready to execute the change set, you can click on the Execute change set button, and you will be asked for the following:
- How should the stack behave in case of failure?
- Roll back all stack resources to the last known stable state
- Preserve the state of successfully provisioned resources, while rolling back failed resources to the last known stable state. Resources without a last known stable state will be deleted upon the next stack operation.
- What should the stack do with the newly created resources during a rollback?
- Retain or delete created resources according to their attached deletion policy.
- Delete created resources during a rollback regardless of their attached deletion policy.

Nested Stacks
If you are repeatedly creating identical resource configurations across multiple templates, you might consider using nested stacks. They are a way to separate the common configurations into dedicated templates. You can create a nested stack within a parent stack by using the AWS::CloudFormation::Stack resource.
Here is an example of a parent stack with two nested stacks – one for a security group and another for an EC2 instance.
The parent template:
AWSTemplateFormatVersion: "2010-09-09"
Description: Parent template with nested stacks for Security Group and EC2 Instance
Parameters:
KeyName:
Description: Name of an existing EC2 KeyPair to SSH into the instance
Type: AWS::EC2::KeyPair::KeyName
Resources:
SecurityGroupStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: <https://s3.amazonaws.com/demo-bucket/s3-nested-stack.yaml>
EC2InstanceStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: <https://s3.amazonaws.com/demo-bucket/ec2-nested-stack.yaml>
Parameters:
KeyName: !Ref KeyName
SecurityGroupId: !GetAtt SecurityGroupStack.Outputs.SecurityGroupId
Outputs:
InstanceId:
Description: The EC2 Instance ID
Value: !GetAtt EC2InstanceStack.Outputs.InstanceId
The security group nested stack template:
AWSTemplateFormatVersion: "2010-09-09"
Description: Security Group for EC2 instance
Resources:
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable SSH access
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 100.200.100.200/32
Outputs:
SecurityGroupId:
Description: The Security Group ID
Value: !Ref InstanceSecurityGroup
The EC2 instance nested stack template:
AWSTemplateFormatVersion: "2010-09-09"
Description: EC2 instance
Parameters:
KeyName:
Description: Name of an existing EC2 KeyPair
Type: AWS::EC2::KeyPair::KeyName
SecurityGroupId:
Description: Security Group ID
Type: String
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t3.micro
KeyName: !Ref KeyName
ImageId: ami-08c40ec9ead489470
SecurityGroupIds:
- !Ref SecurityGroupId
Outputs:
InstanceId:
Description: The Instance id
Value: !Ref EC2Instance
In the CloudFormation console, the nested stacks will have a label NESTED.


Each nested stack can contain other nested stacks. The root stack is the top-level stack to which all nested stacks ultimately belong. If a stack is NESTED, it means it has an immediate parent stack. For the first level of nested stacks, the root stack is also the parent stack.
Drift detection
CloudFormation has a drift detection option that might be useful to run regularly to check whether a resource’s configuration has drifted from its intended configuration.
In the above example, I went and manually changed the inbound rule of the security group. Then I went to the nested stack that deployed it and clicked on Stack actions > Detect drift. A drift detection process started. After it finished, I went to Stack actions > View drift results. This showed me that the security group has been modified.

By choosing the modified resource in the Drifts page, you can click on View drift details and see exactly which property was changed. If you then go to the AWS console, manually revert the change and run Detect drift again, the resource that was previously in MODIFIED status will now show IN_SYNC.
Another option for fixing the sync is to remove the resource from the template and run the stack update operation. After the resource is no longer managed by the stack, you should re-add it and redeploy the stack.
Stack Sets
If you are managing multiple accounts in an AWS Organization, and you need to be able to automatically deploy the same resources to more than one account and to more than one region, you should consider using CloudFormation Stack Sets.
A stack set can be deployed as a normal CloudFormation resource with the AWS::CloudFormation::StackSet type. In this resource, you can specify targets – those are the accounts to which you want to deploy. If you set the root ID of your organization as a target, the described resources in the stack set will be applied to all accounts, and when a new account is added, you can automatically deploy them to it by redeploying the stack set. You can also specify all the regions that you want to provision the needed resources to. We will dive deeper into the specifics of the Stack sets in another post.
Conclusion
CloudFormation provides a powerful way to define and deploy AWS infrastructure using code. You can describe your environment in a consistent and reproducible way by writing templates. Stacks and nested stacks help you organize and manage resources efficiently, while change sets give you visibility into the changes before they are applied, minimizing the risk of errors.
Beyond the basics, CloudFormation offers features like:
- rollback and automatic resource deletion to safeguard the environment;
- execution plans via Change sets that give you visibility into the changes before they are applied, minimizing the risk of errors;
- drift detection option;
- cross-region and cross-account deployment for complex setups via Stacksets.
With CloudFormation, we can automate infrastructure management, improve reliability, and maintain a clear, auditable infrastructure lifecycle.
Explore ITGix services and learn more about our expertise.