When to use Pulumi as an alternative to Terraform

By Sergiu Ibanescu

Pulumi is an open-source Infrastructure as Code (IaC) tool. It promises a very fast learning curve because you can use your favourite language (Javascript/Typescript, Python, Go, Java, .NET) to express your infrastructure. As a result of this main selling point, it is already gaining some traction over Terraform, which is currently the leading open-source IaC tool. So what are the key differences between Pulumi and Terraform? Here, we look at them one by one.

Considerations when choosing an IaC tool

Maintained by HashiCorp, a company that has more than 370 enterprise customers in the Global 2000, Terraform is one of the first options people think of when they need to choose an IaC tool. It uses HCL – a proprietary declarative language – to define the infrastructure configurations. Most of the people who choose Pulumi simply cannot resist the temptation of being able to use their favourite language (which in my case is C#). Incidentally, Terraform does have a Cloud Development Kit (CDK) which you could consider if you find it important to be able to use your favourite language. But the tool is still at version 0.x at the time of writing.

Ideally, when it comes to choosing an IaC tool, you should always take a holistic view and make your decision for one or the other depending on your use case. That’s why I personally consider the following aspects:

  • Productivity
  • Ability to import existing infrastructure and multi-cloud support
  • A big community supporting the tool
  • Easy to integrate in pipelines
  • Easy to maintain/upgrade
  • Ability to test the infrastructure automatically
  • Very good documentation
  • DRY reuse
  • Security

Productivity

Terraform uses the HCL language to express the infrastructure in a declarative way. You can use different editors, but I used Visual Studio Code which also has an extension for Terraform files. Personally, I didn’t benefit a lot from using that extension – autocomplete is basic at most. In contrast, with Pulumi I benefited from Intellisense, since I was ultimately writing a .NET program. However, in .NET at least, the code became a little bit more verbose.

 

Ability to import existing infrastructure and multi-cloud support

Both Terraform and Pulumi support importing an existing infrastructure. However, for Terraform I needed to use aztfexport (https://github.com/Azure/aztfexport) which is intended for generating the configuration files based on existing Azure infrastructure. Even though there is a Terraform import command, there is no native support in Terraform to generate the configuration files.

Pulumi supports importing the existing infrastructure natively. Using the ‘Pulumi import’, you can also generate the code you need to use for that piece of infrastructure. However, writing that command properly requires a deep knowledge about how the resource is expressed in Pulumi world. For example, if you want to import an existing Azure App Service, you need to know that this is an ‘azure-native:web:WebApp’ for Pulumi.

Neither the Terraform tool nor the native Pulumi import command are perfect. For example, I found out that my app settings were not exported as part of a Pulumi import – so don’t expect the process to be smooth.

In terms of multi-cloud support, both Terraform and Pulumi work with multiple cloud providers.

A big community supporting the tool

Terraform definitely has a bigger community than Pulumi, but this is no real surprise since Terraform has been around three years longer than Pulumi. On GitHub, Terraform has 42k stars, compared with 21k for Pulumi. In this respect, Pulumi’s main selling point works against it. For example, when searching for an issue it is more convenient to see posts using one language (i.e. HCL for Terraform). When searching for a potential issue with Pulumi, you may find code in Python, Node.js or even Go. Personally, I find that this makes life a little harder if you need to match it to your Pulumi .NET scenario.

Easy integration in pipelines

Both Pulumi and Terraform can be integrated and run automatically in various pipelines. I tried Terraform with Azure DevOps and GitHub workflows. Even though I didn’t have the chance to integrate Pulumi in a pipeline, I’ve seen that it offers support for various CI/CD systems.

Easy maintenance/upgrades

Since both Pulumi and Terraform ultimately default to the RestApi’s offered by cloud providers, it is important to have the latest and greatest version always available – and Pulumi azure:native comes with that promise. Pulumi will even manage the version selection for you, but you also have the possibility to indicate a specific version of a resource. With Terraform, you have clear control over versions, but if you need new stuff you need to upgrade them manually.

Automatic infrastructure testing

Both Pulumi and Terraform support test automation. However, Pulumi allows me to use my favourite testing framework (XUnit, NUnit or MsTest) which makes this very easy and (once again) productive. When it comes to Terraform, things are a little bit more complicated. You can use HashiCorp Sentinel for ‘rule validations’, build tools to parse the plan and check the expectations, or learn Go and use Terratest (https://terratest.gruntwork.io/).

Good documentation

Both Pulumi and Terraform come with good documentation, but personally I prefer the structure and examples provided by Terraform. In contrast, Pulumi uses the ‘modules’ concept, but it is not easy to map a module ‘app’ to specific Azure resources, plus examples are lacking.

On the other hand, if you like ChatGPT, Pulumi has its own version. Called Pulumi AI, it can generate some code for you with a bit of guidance. Pretty cool stuff, right?

Cool stuff, right?

Reusability

Terraform has the ‘modules’ concept as the main vehicle to share a piece of code between various parts of a program. Pieces of code can also be packed, placed in their own registry and imported across an organization. Pulumi comes with all flavours a language can offer; you can define your own class or create custom components easily. But in my view, this does not secure the crown for Pulumi, since Terraform’s modules are pretty powerful, plus tools – e.g. Terragrunt (https://terragrunt.gruntwork.io/) – have been invented for Terraform due to limitations in this area. And let’s be honest: due to the limited amount of code you need to ‘repeat’, the reusability aspect is not a showstopper.

Security

Pulumi offers better protection of your ‘state secrets’, as it supports encrypting sensitive values (e.g. database passwords, SaaS tokens, credentials files). It’s a pity that Terraform simply stores secrets as plain texts in the state file. Obviously, the remote state can be protected, but if somebody gains access to your state file, they will know a lot of things about your infrastructure, which is never a good thing. Terraform Cloud offers a better level of security, but it is a paid service.

Conclusion

Looking at all these aspects together, we see that in most cases Pulumi can keep pace with its more powerful opponent. Just some reasons to choose Pulumi include the ability to express the infrastructure in your favourite language, its testing simplicity, being a native provider and its secrets management. On the other hand, a common language (HCL), a plethora of tooling, and proven reliability in production scenarios can be reasons for sticking to Terraform.

While I still feel that Pulumi has room for improvement to match Terraform, there are definitely some use cases for which it’s worth giving it a try. Personally, I would use Pulumi in a more limited scenario – e.g. when you don’t need to share/reuse infrastructure with other teams. It’s fine if your team is coding in C#, but if you have a complex product with mixed languages it would probably be better to express the infrastructure in a uniform way.

Additionally, I can recommend trying Pulumi if you want to simplify the tooling part. With Terraform you may end up using a lot of other tools and, at some point, having to learn Go.

About Sergiu Ibanescu

Sergiu is an Expert Software Developer and a Tech Lead at Maxcode, with over 10 years of experience working with .NET and Azure. In his role, Sergiu is constantly looking for new trends and ideas that can help the products he works on and his team, as well as sharing his knowledge to create and maintain the right mix of technical skills

Share this article