A CloudFormation template is more than just a list of resources; it’s a declarative blueprint for your entire cloud infrastructure.

Let’s see it in action. Imagine you need to spin up a simple web server on AWS. You’d start with a template that defines this, and here’s a snippet of what that looks like:

AWSTemplateFormatVersion: '2010-09-09'
Description: A simple EC2 instance for web serving.

Parameters:
  InstanceType:
    Type: String
    Default: t2.micro
    AllowedValues:
      - t1.micro
      - t2.micro
      - m1.small
      - m2.xlarge
    Description: EC2 instance type

Resources:
  MyEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-0abcdef1234567890 # Replace with a valid AMI ID for your region
      InstanceType: !Ref InstanceType
      Tags:
        - Key: Name
          Value: MyWebServer

Outputs:
  InstanceId:
    Description: The Instance ID of the EC2 instance
    Value: !Ref MyEC2Instance
  PublicIp:
    Description: The Public IP address of the EC2 instance
    Value: !GetAtt MyEC2Instance.PublicIp

This template is broken down into key sections that define the "what" and "how" of your cloud deployment.

The AWSTemplateFormatVersion is pretty straightforward – it tells CloudFormation which version of the template language you’re using. Description is for human readability, a quick note about what this template does.

The Parameters section is where you make your templates dynamic. Instead of hardcoding values, you define input parameters that users can specify when they create a stack. In our example, InstanceType allows someone to choose the EC2 instance size. You can set Default values, AllowedValues to restrict choices, and provide a Description to guide the user. This is crucial for reusability; one template can deploy the same infrastructure with different configurations.

The heart of the template is the Resources section. This is where you declare the actual AWS resources you want to create, like EC2 instances, S3 buckets, RDS databases, or VPCs. Each resource has a logical ID (e.g., MyEC2Instance), a Type (e.g., AWS::EC2::Instance), and Properties that configure that specific resource. Here, ImageId specifies the Amazon Machine Image for our EC2 instance, and InstanceType is set using !Ref InstanceType, referencing the parameter we defined earlier. The Tags are metadata for organizing your AWS resources.

Finally, the Outputs section allows you to export information about your created resources. This is incredibly useful for referencing values from one stack in another, or simply for displaying important details after deployment. For our EC2 instance, we output its InstanceId and PublicIp. !Ref MyEC2Instance gets the physical ID of the EC2 instance, while !GetAtt MyEC2Instance.PublicIp retrieves a specific attribute (the public IP address) of that instance.

When you create a stack from this template, CloudFormation reads these sections. It takes your parameter inputs, creates the specified resources in the correct order (handling dependencies automatically), and then presents you with the outputs. For instance, if you chose t2.micro for InstanceType and your instance got the IP 54.1.2.3, CloudFormation would make i-012345abcdef67890 and 54.1.2.3 available in the Outputs tab of your stack.

The underlying mechanism that allows !Ref and !GetAtt to work is CloudFormation’s intrinsic functions. These aren’t just simple substitutions; they represent a way to query and reference values within the template or from created resources. !Ref is versatile; when used with a parameter, it returns the parameter’s value. When used with a resource, it typically returns the resource’s physical ID. !GetAtt is more specific, retrieving an attribute of a resource, like its ARN, Public IP, or Endpoint.

Understanding how CloudFormation processes these sections and intrinsic functions is key to building robust, automated infrastructure.

The next logical step is to explore how to manage dependencies between resources within your template.

Want structured learning?

Take the full Cloudformation course →