Infrastructure as Code: Terraform vs CloudFormation
Within the MentorMate Cloud Center of Excellence team (CCOE), we don’t limit ourselves to a single IaC tool. Instead, we consider the strengths and weaknesses of each, so we can select what works best for a particular project. This blog reviews the pros and cons of AWS CloudFormation and HashiCorp Terraform as IaC tools. For more detailed information on the advantages of Infrastructure as Code, read our blog post on the subject.
Both of the tools compared are declarative, meaning that an engineer must define the desired state of the infrastructure. Under the hood, the declarative tool figures out resource dependencies to create, update and delete resources in the correct order.
What is AWS CloudFormation?
CloudFormation is the built-in Infrastructure as Code service in the AWS cloud. When you use CloudFormation, you work with templates and stacks. You define all your cloud resources in a template. When you build a stack out of a template, CloudFormation creates, updates, and deletes cloud resources to match the state defined in your template.
CloudFormation powers two AWS frameworks. One is CDK, which helps developers define cloud infrastructure using their favorite programming language. The other is Serverless Application Model (SAM), which, as its name suggests, simplifies the provisioning of serverless applications.
What is Terraform?
HashiCorp Terraform is another prevalent Infrastructure as Code tool. It comes in two variations: an open-source, free-to-use tool that runs locally or as part of your CI/CD pipelines and Terraform Cloud — a managed service offering.
“Terraform creates and manages resources on cloud platforms and other services through their application programming interfaces (APIs). Providers enable Terraform to work with virtually any platform or service with an accessible API. HashiCorp and the Terraform community have already written more than 1700 providers to manage thousands of different types of resources and services, and this number continues to grow.” — Terraform.io
Terraform vs CloudFormation: Versatility
What is evident at first glance is that Terraform is extendable and provides support for different platforms and services. It allows you to manage resources across other cloud vendors (such as AWS, Azure, GCP, etc.) and even hardware devices such as Cisco switches and routers on-premises.
Not long ago, AWS introduced a CloudFormation public registry with CloudFormation extensions published by third parties (such as Datadog, JFrog, Snyk, etc.). Using those extensions offers the ability to manage resources outside the AWS cloud. However, those options are still quite limited.
Overall, if your cloud presence spans different clouds or you’re dealing with a hybrid cloud, Terraform might be your best bet! Otherwise, if you are all-in with AWS and need to manage just a handful of 3rd party resources with IaC, CloudFormation extensions and custom resources are sufficient.
Terraform vs CloudFormation: Stability
When you decide to adopt Infrastructure as Code, it’s best to avoid making IaC-managed resources depend on manually created ones and vice versa as much as you can. That’s because you can quickly run into IaC deployment failures and inconsistencies across environments (one of the advantages of using IaC in the first place). You’ll need to initially invest time to describe the entire Infrastructure as Code and consider the stability of the IaC tool as it is an essential factor.
AWS CloudFormation has proven itself as a rock-solid foundation. In the release history of the tool, you can see that most of the changes only introduce new supported resources, and there are no backward-incompatible changes. We have firsthand experience with this — we use CloudFormation templates written years ago with no problems and haven’t wasted time refactoring them. There are simply no breaking changes introduced to CloudFormation.
Unfortunately, that’s not always the case with Terraform. You can certainly enforce the version of Terraform itself and the version of the providers you use to guarantee repeatable deployments. However, the problems come when you continuously expand your infrastructure and take advantage of cutting-edge services.
At some point, you must upgrade your provider version to a newer one., Often, this isn’t a straightforward process as there might be backward-incompatible changes. You can see what it would take to upgrade the Terraform AWS provider from version 3 to 4 in this guide.
If other factors covered in this blog tip the scales in favor of Terraform, you might consider using CloudFormation because of its stability.
Terraform vs CloudFormation: Reusability
You can easily reuse a well-written and parameterized code defining a piece of infrastructure for different use cases. There is no need to describe an AWS RDS Database instance every time you need it. Instead, define it once and pass everything that may change as variables/parameters to suit it to different architectures. This approach is fundamental to us and allows our company to quickly deliver more value to our clients.
Terraform organizes code in modules. “A module is a container for multiple resources used together. Modules can be used to create lightweight abstractions so that you can describe your infrastructure in terms of its architecture, rather than directly in terms of physical objects.”
The concept of modules is not new and is available in many programming languages.
But Terraform is very mature in this aspect. There’s an entire Terraform registry with thousands of modules contributed by the community that users can reuse with little or no modification.
CloudFormation modules have only been available since November 2020. As this is relatively new in CloudFormation, the number of modules available in its registry is not even close to that of Terraform. That doesn’t necessarily mean users couldn’t reuse CloudFormation templates before this date. Even after introducing modules, nested stacks still seem to be the preferred way of writing reusable CloudFormation templates (“Nested stacks are stacks created as part of other stacks. You create a nested stack within another stack by using the AWS::CloudFormation::Stack resource”).
Both Terraform and CloudFormation have the needed capabilities to allow you to write reusable code. However, Terraform stands out with its centralized registry and all the code you can take and start building.
Terraform vs CloudFormation: Specifics
There are other specifics of both tools that might also facilitate your decision.
CloudFormation templates are authored in either well-known JSON or YAML formats, while Terraform uses its own configuration language based on the more common HashiCorp HCL format.
Terraform supports complex data types such as objects and powerful built-ins, including loops and functions to manipulate data on the fly. In CloudFormation, the data types of the input parameters are more limited. Suppose you need to loop or modify data. In that case, you need to use macros, which are essentially custom-made Lambda functions that apply processing to your templates but require basic scripting knowledge and quickly become tedious.
Both tools keep track of the provisioned real-world resources in a state. The state plays a vital role in each deployment. When you pass your modified code to the tool, it checks the current state of the provisioned infrastructure against the new code you feed to determine which changes to apply.
CloudFormation manages its state internally, which takes away some of the developers’ responsibility. With Terraform, however, you need to take care of that yourself. If an entire team collaborates on the infrastructure code, they must place the state centrally and enforce locking to avoid situations where two developers try to deploy simultaneously. Having control over the state can be beneficial at times. For example, you can manipulate the state if you want to rename resources in your definitions. The same change will end up recreating all renamed resources with CloudFormation.
One last specific thing worth mentioning is the rollback on failure capability. By default, if a failure occurs, CloudFormation rolls back all changes completely to their previous state during deployment. The behavior of Terraform in the same situation is different. The tool marks the failed resource(s) “tainted” and stops processing. You must revert your code to a previous commit in source control and reapply to roll back the wrong change.
All these specifics make Terraform’s learning curve steeper than CloudFormation, but CloudFormation has fewer built-in functionalities. Ultimately, it’s down to what the developers are most comfortable with using. Make sure the team is passionate about your chosen IaC tool.
Terraform vs CloudFormation: Final Thoughts
Both AWS CloudFormation and HashiCorp Terraform are widely used and will be for the foreseeable future. Choosing one or the other depends not only on how your infrastructure looks today but also on its future state. Utilizing Infrastructure as Code is a good investment that will pay off in the long run by ensuring predictable deployments, cost optimization, and time efficiency. Moreover, your entire team will continue to add value to your business instead of spending time troubleshooting inconsistency problems.