Table of Contents

For the majority of my career I have worked in AWS shops and (mainly) with Terraform. Neither of course is the only way and I would always argue against the ‘golden hammer’ mentality towards any tool or tooling. What are the pros and cons of CloudFormation with respect to Terraform? What experience have I had with CloudFormation? What is CloudFormation like today? Obvious(?) disclaimer: This article is written in the context of AWS services managed as code.

Some pros and cons

Terraform has a bigger community (because it uses the same syntax across hundreds of providers) and more advanced handling for querying data, especially from outside the AWS domain, than CloudFormation. On the other hand it doesn’t have the first party support on AWS that you get with CloudFormation and getting support can be slow (for Open Source/BUSL versions) and/or expensive (Terraform Cloud/Enterprise subscription) in the event that you need it. Of course Terraform uses Hashicorp Configuration Language which is a (slightly) higher barrier to entry than ‘plain’ YAML/JSON for CloudFormation. As an aside, perhaps an advanced case, I can see some of the Terraform variables here looking a bit bewildering to newcomers! In the context of AWS, both Terraform and Cloudformation have been based around the idea of a deployment to a single account and single region. CloudFormation offers StackSets as a native feature to expand in both dimensions. Terraform can alias providers within a single plan for regions and accounts at larger scale but this is static - there is no inheritance for new entities without redeploying and access for each has to be managed separately and statically. There are third party orchestration tools such as Terragrunt and self-managed methods involving partial configuration but these can be challenging in themselves. It is perhaps ironic that it isn’t uncommon in large Terragrunt deployments to render Terraform variables with YAML also.

My own previous experience

I was working on an AWS Control Tower Organisation. Account Factory for Terraform did not yet exist. We wanted a solution that could manage and use delegated administrator for IAM cross-account access. CloudFormation StackSets were a solution. It was painful to deploy CloudFormation using Terraform - in some cases working to the lowest common denominator of both toolsets- but it did work. It was a bit of a surprise setting up the IAM permissions for self-managed execution permissions since these are not needed for Terraform but once done we had the advantage that inheritance was ’live’ for any change to code or to our environment, e.g. it was possible to deploy to an Organisational Unit and to have our stack deployed to a new account when it became a member of that OU. There is no real counterpart in Terraform.

Returning to the present

It’s relatively straightforward to create a simple CloudFormation stack. I recently created a small demo example in YAML format. Arguably the single YAML file for this (not using nested stacks or modules) is simpler here than the equivalent Terraform would be, and being YAML there isn’t very much in the way of Domain Specific Language. I also created a demo deploying a StackSet and the resources needed to make that work. Again there is ’less’ to this than there would be with Terraform which may be considered an advantage.

Update: I created an equivalent Terraform plan for the ‘same’ resources as the above CloudFormation-StackSet-Demo. This allows a direct comparison for this very simple use case of the two toolchains. Notably Terraform does not have a pre-requisite for dedicated IAM roles to be set up first. I have also not shown remote state and lock table management to prevent multiple simultaneous executions- these are optional for a demo-level project. On the other hand we can see that there isn’t really an equivalent to StackSet instances - here the resources in each region are ‘separate’ in their queries to the environment, their creation, their outputs, and a separate provider alias needs declaring in each case. Whilst terraform of course supports modules, little would change here in these respects save that the plan would be a little more complex.

CI/CD Options

Obviously in a production setting you would not want a workstation deployment and there are more involved CI/CD solutions more suited to a production environment, including:

An (interim) conclusion

Which is better? Depends really on your use case - both Terraform and CloudFormation can be driven by CDK and as I have written previously I see Terraform gradually becoming an intermediate language, e.g. with Wing, as toolchains develop. I would say that each has its place. Terraform has the advantage that you can use it across many different platforms, even to order a pizza. CloudFormation by contrast has first party support from the same people you are deploying your stuff to - so a one stop shop, native cross-region and cross account support, and management of inheritance that Terraform does not. You can also avoid the bootstrapping problem that ‘plain’ Terraform has with setting up remote state storage and lock table and you don’t have to worry about setting up your own third party deployment pipeline or runners since AWS provide and support this first-party if you wish. Domain Specific language aside, Perhaps the most key difference is the support in CloudFormation StackSets for managing inheritance, e.g. automatically deploying or destroying resources based on external conditions/future events, for which Terraform has no real equivalent.