Skip to content
AWS aws deployment 5 min read

What is CloudFormation?

AWS CloudFormation is Amazon’s native Infrastructure as Code (IaC) service — a way to describe the cloud resources you want in a text file and let AWS build them for you. You write a template (a JSON or YAML file listing servers, networks, databases, and how they connect), hand it to CloudFormation, and it provisions everything in the right order, tracks what it created, and cleans up after itself if something goes wrong. This matters because it turns “click 20 buttons and hope you remember” into a repeatable, reviewable file you commit to Git.

What CloudFormation actually does

You give CloudFormation a template. It reads the resources you declared and creates a stack — a single named collection of all those resources managed together as one unit. From then on, the stack is the thing you operate on: you update it, you delete it, you inspect it.

Three jobs CloudFormation handles for you automatically:

  • Dependency ordering. If a server needs a security group (a virtual firewall) before it can launch, CloudFormation figures that out from the references in your template and creates them in the correct sequence. You do not write the order yourself.
  • State tracking. CloudFormation remembers exactly what it created and the settings of each resource. Unlike Terraform, there is no separate state file for you to store and protect — AWS keeps the state for you inside the stack.
  • Rollback on failure. If creating the stack fails partway through, CloudFormation rolls back and deletes everything it made, so you are not left with half-built, half-billed infrastructure.

Because the state lives inside the stack on AWS, you never have to manage, lock, or back up a state file the way Terraform users do. This is one of CloudFormation’s biggest day-one wins for AWS-only teams.

When to use CloudFormation (and when not to)

When to use it: you are committed to AWS, you have more than one environment (say, staging and production), and you want IaC without paying for or learning an extra tool. CloudFormation itself is free — you only pay for the resources it creates. It has the deepest, fastest support for new AWS services because Amazon builds it.

When NOT to use it: you need to manage resources across multiple clouds (use Terraform), or you want to define infrastructure using a real programming language with loops and conditionals (use the AWS CDK, which compiles down to CloudFormation anyway). Raw YAML templates can also get verbose for very large systems.

ToolLanguageBest forExtra cost
CloudFormationYAML / JSONAWS-only teams wanting native IaCNone
AWS CDKTypeScript, Python, etc.Developers who prefer real codeNone
TerraformHCLMulti-cloud, large ecosystemsFree (paid Cloud option)

A minimal template

A template has a Resources section listing what to create. Here is one that makes an S3 bucket (object storage) and a security group, written in YAML:

AWSTemplateFormatVersion: "2010-09-09"
Description: A tiny stack with a bucket and a security group

Resources:
  AppBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: devcraftly-app-assets-2026

  WebSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTPS from anywhere
      VpcId: vpc-0a1b2c3d
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0

The AWSTemplateFormatVersion is just a fixed format date — always "2010-09-09" — and must stay quoted so the build does not read it as a number.

Creating a stack

You can deploy a template from either the AWS Management Console (the web dashboard) or the AWS Command Line Interface (CLI — the terminal tool, v2 in 2026).

Console steps:

  1. Open the CloudFormation service in the Console.
  2. Click Create stack then With new resources (standard).
  3. Under Specify template, choose Upload a template file and select your YAML file.
  4. Click Next, give the stack a name like app-stack, and click Next again.
  5. Review the resources, then click Submit.

CLI equivalent:

aws cloudformation create-stack \
  --stack-name app-stack \
  --template-body file://template.yaml \
  --capabilities CAPABILITY_NAMED_IAM

Output:

{
    "StackId": "arn:aws:cloudformation:us-east-1:111122223333:stack/app-stack/0a1b2c3d-1234-5678-90ab-0a1b2c3d4e5f"
}

The --capabilities flag is required only when a template creates IAM (Identity and Access Management — AWS permissions) resources, which acknowledges you reviewed those permissions.

To watch progress, ask for the stack’s events:

aws cloudformation describe-stack-events --stack-name app-stack \
  --query "StackEvents[].{Resource:LogicalResourceId,Status:ResourceStatus}"

Output:

[
    { "Resource": "WebSG",     "Status": "CREATE_COMPLETE" },
    { "Resource": "AppBucket", "Status": "CREATE_COMPLETE" },
    { "Resource": "app-stack", "Status": "CREATE_COMPLETE" }
]

Updating and deleting

To change infrastructure, edit the template and update the stack — CloudFormation works out the difference and changes only what is needed.

aws cloudformation update-stack \
  --stack-name app-stack \
  --template-body file://template.yaml

A change set lets you preview those changes before applying them — create one with aws cloudformation create-change-set and inspect it before executing. To tear everything down, delete the stack and CloudFormation removes every resource it created:

aws cloudformation delete-stack --stack-name app-stack

The drift gotcha

This is the trap that catches everyone. Once a resource is owned by a stack, treat it as off-limits to manual editing. If you open the Console and change a stack-managed security group rule by hand, reality no longer matches the template. This mismatch is called drift.

Drift is dangerous for two reasons. First, your next update-stack may silently revert your manual fix back to whatever the template says, undoing your change. Second, an update can outright fail if CloudFormation expected a resource in a state it no longer finds. You can detect this with drift detection (aws cloudformation detect-stack-drift --stack-name app-stack), but the real cure is discipline: change the template, never the live resource.

Warning: failed stack creates roll back and delete everything by default. That is usually what you want, but it also means a typo near the end of a long template can throw away 15 minutes of provisioning. For production stacks, consider --disable-rollback while debugging so you can inspect what failed.

Best practices

  • Treat stack-managed resources as owned by the template — never edit them by hand in the Console, to avoid drift.
  • Keep templates in version control (Git) and review changes like any other code.
  • Use change sets to preview updates before applying them, especially in production.
  • Split large systems into multiple smaller stacks (network, app, data) so a failure has a smaller blast radius.
  • Add a DeletionPolicy: Retain to stateful resources like databases and S3 buckets so deleting a stack does not wipe your data.
  • Always quote version strings and numeric-looking values in YAML to keep templates valid.
  • Run drift detection periodically to catch out-of-band changes before they break a deploy.
Last updated June 15, 2026
Was this helpful?