Articles

Infrastructure as Code Explained: Terraform vs AWS CloudFormation

In modern cloud environments, manually managing infrastructure via dashboards or scripts can be slow and error-prone. To fix this, our teams can utilize infrastructure as code (IaC), which defines infrastructure using machine-readable configurations. IaC tools enable automatic deployment of cloud architectures, networks, servers, and storage with a single command, simplifying scaling, disaster recovery, and collaboration. Let’s now explore two of the most widely adopted infrastructure as code tools, Terraform and AWS CloudFormation. We’ll also understand how these two differ in design, syntax, and management.

  • Learn Terraform Infrastructure as Code covering essential concepts, provisioning techniques, deployment best practices and infrastructure management skills.
    • Includes 44 Courses
    • With Certificate
    • Intermediate.
      30 hours

What is infrastructure as code (IaC)?

Infrastructure as code is the practice of managing and provisioning infrastructure through code rather than manual configuration or scripts. Instead of clicking through the AWS Console or running ad-hoc shell commands, IaC uses configuration files that describe resources in a declarative or imperative way.

Old way of cloud computing instead of IaC

Using IaC for cloud computing

The primary benefits of infrastructure as code include:

  • Consistency: The same configuration file can create identical environments for development, staging, and production.
  • Version control: Infrastructure changes can be tracked and reviewed using Git or similar systems.
  • Scalability: Resources can be easily duplicated or modified at scale.
  • Reduced human error: Manual configurations are replaced by repeatable, automated processes.
  • Faster recovery: Environments can be recreated quickly in case of outages or data loss.

Tools like Terraform and AWS CloudFormation bring these ideas into practice. Both allow developers to define what their infrastructure should look like, but they differ in implementation and flexibility.

In the next section, we’ll understand how each of these tools works and how they approach infrastructure as code.

Understanding Terraform and AWS CloudFormation

Terraform and CloudFormation both enable IaC, but they serve slightly different audiences and ecosystems.

Terraform is an open-source IaC tool developed by HashiCorp. It uses a declarative language called HCL (HashiCorp Configuration Language) to define and provision infrastructure resources. One of Terraform’s most significant advantages is its multi-cloud support — it can manage resources across AWS, Azure, GCP, and other providers within a single configuration.

AWS CloudFormation, on the other hand, is AWS’s native IaC solution. It allows developers to define infrastructure using YAML or JSON templates that are tightly integrated into the AWS ecosystem. CloudFormation is ideal for teams that operate entirely within AWS and want strong integration with its native services, IAM roles, and monitoring tools.

While both tools share a declarative nature, Terraform emphasizes cross-cloud flexibility and modularity, whereas CloudFormation focuses on AWS-specific optimization and native automation.

What’s the difference between Terraform and CloudFormation syntaxes?

Terraform uses HCL, which is simpler and easier to read. CloudFormation uses YAML, which is longer and more detailed, but closely follows AWS’s resource structure.

To demonstrate, consider creating an Amazon S3 bucket in both tools.

S3 bucket configuration in Terraform (HCL)

Terraform uses HCL, a readable configuration language, to define resources. The block below describes a private S3 bucket with a specific name.

resource "aws_s3_bucket" "my_bucket" {
bucket = "example-bucket"
acl = "private"
}

When you run:

terraform init
terraform apply

Terraform reads this file and automatically creates the bucket.

S3 bucket configuration in AWS CloudFormation (YAML)

CloudFormation uses YAML to describe AWS resources. The template below defines the same S3 bucket using AWS’s native syntax.

Resources:
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: example-bucket
AccessControl: Private

When deployed:

aws cloudformation deploy \
--template-file bucket.yaml \
--stack-name my-bucket-stack

CloudFormation interprets this template and builds the bucket as part of a stack.

Understanding Terraform and CloudFormation syntax

Terraform defines resources using a resource block. In this structure, you specify the provider (in this case, aws), the resource type (such as s3_bucket), and all necessary configuration values. The syntax is concise, readable, and easily reusable across different cloud platforms, which makes Terraform an excellent choice for multi-cloud environments.

On the other hand, CloudFormation follows AWS’s native resource structure. Each resource is declared under the Resources section, and its properties adhere strictly to AWS’s API naming conventions. While this makes CloudFormation more detailed, it also results in a tighter integration with AWS features, including validation and error reporting within the AWS Console.

Although both configurations achieve the same goal of creating an S3 bucket, Terraform emphasizes flexibility and portability, whereas CloudFormation offers a deeply integrated, AWS-focused experience.

How modularization works in Terraform and CloudFormation

As infrastructure grows, keeping everything in a single file becomes challenging to manage. Both Terraform and CloudFormation provide ways to organize configurations into smaller, reusable units. This makes your setup easier to maintain and reduces duplication.

Terraform modules

In Terraform, modules are the primary way to group related resources. A module is simply a folder containing Terraform configuration files. You can call these modules from your main configuration to keep your setup clean and reusable.

Here’s an example of using a local VPC module:

module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
}

This code imports a module stored in the modules/vpc directory and passes it a variable (cidr_block) for customization. The benefit is that the VPC logic remains within the module, allowing you to reuse it across multiple environments without modifying the internal code.

Terraform modules can also be versioned and shared through the Terraform Registry, where teams publish well-tested, community-maintained modules for common infrastructure patterns.

CloudFormation nested stacks

CloudFormation handles modularization through nested stacks. A nested stack allows one CloudFormation template to call another template as if it were a resource. This keeps large architectures organized by separating concerns — for example, placing networking, application, and database resources into different templates.

Example nested stack reference:

Resources:
VPCStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://example.com

In this example, the main template references another template hosted at a placeholder URL. That referenced template can define the entire VPC configuration. This approach helps teams maintain clear boundaries between components and update them independently.

Comparing Terraform and CloudFormation

  • Terraform modules provide versioning and multi-cloud portability.
  • CloudFormation nested stacks offer tight AWS integration and native dependency resolution.
  • Both approaches enhance maintainability and reduce redundancy, but Terraform’s modular design is generally easier to scale across providers.

Understanding state management in IaC tools

State management determines how each tool tracks deployed resources. Terraform and CloudFormation handle state differently, and understanding this distinction is critical for maintaining infrastructure consistency.

Terraform state management

Terraform keeps track of resource configurations and their current states in a file called terraform.tfstate. This state file is essential for detecting changes (drift) and planning updates safely.

Example backend configuration for remote state storage:

terraform {
backend "s3" {
bucket = "terraform-state-bucket"
key = "global/s3/terraform.tfstate"
region = "us-east-1"
}
}

This configuration stores Terraform’s state file in an S3 bucket and uses DynamoDB for state locking to prevent concurrent updates. This setup ensures reliability in collaborative environments.

Terraform’s state model provides full visibility into infrastructure, but it requires careful security management — especially when storing state files remotely.

CloudFormation stack state

CloudFormation manages state automatically. Every deployment creates a stack, and AWS keeps track of all resources associated with that stack. This approach removes the need for manually managing state files.

Changes are handled as stack updates, and users can monitor progress directly in the AWS Console or via the CLI. CloudFormation also supports Change Sets, which preview modifications before applying them.

Comparing both the state management tools

  • Terraform requires explicit backend configuration but allows fine-grained control over state and storage.
  • CloudFormation offers hands-free management, but it’s limited to AWS and less transparent for external automation.

When to choose Terraform or CloudFormation

Choosing between Terraform and CloudFormation depends on project scope, ecosystem, and operational needs.

Use case Choose Terraform Choose CloudFormation
Multi-cloud setup Yes, supports multiple providers AWS-only
Modularity and reuse Advanced module system Nested stacks available
Ease of use Cleaner syntax (HCL) Familiar YAML structure for AWS
State management Flexible but manual Managed automatically by AWS
Ecosystem integration Works with CI/CD, Vault, Kubernetes Seamless AWS integration

Flowchart showing how to choose between Terraform and AWS CloudFormation

Terraform is ideal for teams managing diverse cloud infrastructures. CloudFormation is perfect for AWS-focused organizations that prioritize deep service integration and built-in security.

Best practices for infrastructure as code

  • Store all IaC configurations in version control systems such as Git.
  • Use remote state backends for shared environments.
  • Validate configurations using tools like tflint (Terraform) or cfn-lint (CloudFormation).
  • Keep environments isolated (dev, staging, production).
  • Apply the principle of least privilege when assigning IAM roles for IaC automation.
  • Regularly scan IaC templates for vulnerabilities or misconfigurations.

Following these practices ensures reliability, security, and maintainability in any infrastructure workflow.

Conclusion

Infrastructure as code is a vital part of modern DevOps, and both Terraform and AWS CloudFormation are trusted options for setting up and managing cloud infrastructure. Terraform is appreciated for its flexibility and support across various providers, while CloudFormation offers a seamless experience that is fully integrated with AWS.

As you become familiar with these tools and choose the best approach for your infrastructure strategy whether you’re working across multiple cloud platforms or developing more sophisticated AWS solutions you can boost your skills through targeted learning paths. Starting with the Foundations of Cloud Computing course and then exploring the Important DevSecOps Tools path will help you acquire the knowledge to design secure, scalable, and easy-to-maintain cloud systems.

Frequently asked questions

1. What is the main difference between Terraform and CloudFormation?

Terraform is a multi-cloud, open-source IaC tool that works across AWS, Azure, GCP, and many other platforms. CloudFormation is an AWS-native IaC service designed specifically for managing AWS resources.

2. Can Terraform manage AWS CloudFormation stacks?

Yes. Terraform can manage CloudFormation stacks using the aws_cloudformation_stack resource. This allows teams to use Terraform as their main IaC tool while still deploying CloudFormation templates when necessary.

3. How does Terraform handle state locking in collaborative projects?

Terraform uses state locking to prevent multiple users from modifying infrastructure simultaneously. When using a remote backend like S3 with DynamoDB, the DynamoDB table serves as the lock, ensuring safe and conflict-free updates.

4. What are CloudFormation change sets used for?

CloudFormation change sets allow you to preview the exact changes AWS will make before applying them. This helps you understand impacts such as resource replacements or deletions before running the update.

5. Which tool is better for multi-cloud deployments?

Terraform is ideal for multi-cloud environments because it supports many providers, has consistent syntax, and offers reusable modules across different clouds. CloudFormation is limited to AWS.

Codecademy Team

'The Codecademy Team, composed of experienced educators and tech experts, is dedicated to making tech skills accessible to all. We empower learners worldwide with expert-reviewed content that develops and enhances the technical skills needed to advance and succeed in their careers.'

Meet the full team

Learn more on Codecademy

  • Learn Terraform Infrastructure as Code covering essential concepts, provisioning techniques, deployment best practices and infrastructure management skills.
    • Includes 44 Courses
    • With Certificate
    • Intermediate.
      30 hours