The most reliable way to automate creating, updating, and deleting your cloud resources is to describe the target state of your infrastructure and use a tool to apply it to the current state of your infrastructure (see Understanding Infrastructure as Code). AWS CloudFormation and Terraform are the most valuable tools to implement Infrastructure as Code on AWS.
I have worked with CloudFormation and Terraform in various projects. You will learn about the differences between CloudFormation and Terraform in this article.
Do you prefer listening to a podcast episode over reading a blog post? Here you go!
Before we start, both tools are following a very similar approach.
- You define a template (CloudFormation) or configuration (Terraform) describing the target state of your infrastructure.
- The tool (CloudFormation or Terraform) calculates the necessary steps to reach the defined target.
- The tool (CloudFormation or Terraform) executes the changes.
But what are the differences between both tools?
CloudFormation covers most parts of AWS and needs some time to support new service capabilities. Terraform covers most AWS resources as well and is often faster than CloudFormation when it comes to supporting new AWS features. On top of that, Terraform supports other cloud providers as well as 3rd party services. A shortened list of vendors supported by Terraform: Google Cloud Platform, Azure, GitHub, GitLab, Datadog, many more.
Depending on your infrastructure, a big or at least small plus for Terraform.
Update: CloudFormation released Resource Providers in November 2019 to allow 3rd party integrations. So far, this new feature is not used very much and not very user-friendly.
CloudFormation is a service offered by AWS for free. The AWS support plans include support for CloudFormation.
Terraform is an Open Source project. Hashicorp, the company behind Terraform, is offering support plans as well.
When already subscribed to an AWS support plan, that might be a plus for CloudFormation. If you prefer Open Source, that is a plus for Terraform.
Both tools need to keep track of all the resources under management. CloudFormation is managing its state with so-called stacks. By default, Terraform is storing its state on disk. Terraform is offering remote state as well, for example, based on S3 and DynamoDB or Terraform Cloud. It is advisable to use remote state when multiple users are working on the same infrastructure in parallel.
CloudFormation manages state within the managed service out-of-the-box, which is a small plus compared to Terraform, where you need to configure remote state yourself.
Infrastructure for a typical web application consists of a lot of resources: VPC, Subnets, Security Groups, Auto Scaling Group, Elastic Load Balancer, to name a few. Specifying all these resources in a single blueprint will cause you headaches when maintaining the system in the future. Using small modules that you stick together as needed is a common approach. Terraform comes with native support for modules. You can find open-source modules in the Terraform Registry. CloudFormation does not have first-class support for modules. It provides some features that you can use to modularize your templates, but it is up to you to do so. The biggest challenge is to pass values from one “module” to another. The export feature of CloudFormation provides a way to share outputs, but they are not allowed to change! CloudFormation lacks a central place where templates are shared.
Handling modules with Terraform is simple. CloudFormation is offering multiple ways to create “modules” with different pros and cons. I’d award Terraform with a plus for usability.
CloudFormation and Terraform do not only allow you to create your infrastructure from scratch automatically. You can use both tools to update your infrastructure later as well.
CloudFormation offers change sets that you can use to verify changes. Terraform provides a command named
plan, which gives you a very detailed overview of what will be modified if you apply your blueprint.
Terraform presents a detailed and readable summary of the changes that will be applied. That’s a big plus compared to the basic overview CloudFormation is providing with a change set.
It is useful to be able to add wait conditions to your infrastructure automation from time to time. For example, if you want to wait until a service has been started on a virtual machine. Using wait conditions allows you to wait for signals sent via HTTPS before dependent resources are created or updated when using CloudFormation.
Being able to use wait conditions is a plus for CloudFormation. Terraform does not support wait conditions.
What happens when you change a Launch Configuration of an Auto Scaling Group within your blueprint? When using an update policy, CloudFormation will perform a rolling update, including a rollback in case of a failure. Terraform does not support rolling updates for Auto Scaling Groups out-of-the-box. With Terraform’s create_before_destroy, you can implement a way to deploy new AMIs without downtime in a blue/green fashion, but you will run into issues if you have a dynamic number (auto-scaling) of instances in the ASG.
Supporting rolling updates for Auto Scaling Groups is a plus for CloudFormation.
When CloudFormation fails to modify your infrastructure, it rolls back to the previous working state automatically. Terraform does not support rollbacks out of the box. Either you decide to fix the problem and deploy it again, or you have to apply the previous configuration yourself.
Both CloudFormation and Terraform support a “prevent from deletion” feature. This is handy to ensure that a resource can never be deleted by accident. CloudFormation goes one step further and can perform a backup of many data stores before it deletes or replaces them.
CloudFormation can import existing resources for a small number of resource types. Terraform allows you to import existing resources. On top of that data, providers enable you to query attributes from existing resources.
Handling existing resources is better supported in Terraform.
CloudFormation can import encrypted secrets from AWS Secrets Manager and AWS SSM. The secret values are never stored in CloudFormation. Terraform supports reading secrets from remote backends and environment files. The big risk is that Terraform always stores the unencrypted secret value in the state file!
CloudFormation is better at handling secrets such as database passwords!
CloudFormation comes with first-class support to enable or disable resources if a condition is met. There is no way to loop in CloudFormation over an array natively. Terraform comes with support for loops and also uses those loops to enable or disable a resource if a condition is met.
Conditions are slightly easier in CloudFormation, while loops are only possible in Terraform.
CloudFormation can tag all resources in a stack with a set of tags out-of-the-box. In Terraform, it is up to you to add the tags to every resource.
It is easier to ensure consistent tagging in CloudFormation.
While using both tools to spin up AWS infrastructure, I believe that the CloudFormation Linter detects more issues.
CloudFormation and Terraform are both powerful and mature tools. Going through the differences listed above will help you to make a decision. I select the tool depending on the requirements for every project. If there is no clear winner, I tend to use CloudFormation.