The IaC Tool Landscape
“Infrastructure as Code” is not a single product, it is a category, and the category is crowded. Terraform, OpenTofu, Pulumi, CloudFormation, the AWS CDK, Bicep, and Ansible all live under the IaC banner, but they make very different trade-offs around language, cloud lock-in, and what part of the lifecycle they own. Picking the right one starts with understanding two fault lines that run through the whole ecosystem: provisioning versus configuration management, and cloud-agnostic versus cloud-native. This page maps the landscape so you know exactly where Terraform sits and why this guide chose it.
Provisioning vs configuration management
The first split is about what a tool manages.
Provisioning tools create and destroy infrastructure: VPCs, load balancers, databases, Kubernetes clusters, DNS records. They talk to cloud control-plane APIs and answer the question “does this resource exist, and does it match my definition?” Terraform, OpenTofu, Pulumi, CloudFormation, CDK, and Bicep are all provisioning tools.
Configuration management tools assume a machine already exists and shape what runs inside it: installing packages, editing config files, starting services, applying OS patches. Ansible, Chef, Puppet, and SaltStack live here.
The line blurs in practice. Ansible has modules that provision cloud resources, and Terraform can run a remote provisioner to bootstrap a host. But each tool is sharpest at its core job. The modern convention is to provision with Terraform and configure with Ansible (or, increasingly, with immutable images built by Packer so there is nothing left to configure at runtime).
Tip: If you find yourself writing Terraform
remote-execprovisioners to install software on a server, that is a signal to reach for a configuration-management tool or a pre-baked image instead. Provisioners are a last resort, not a strategy.
Cloud-agnostic vs cloud-native
The second split is about which clouds a tool speaks to.
Cloud-agnostic tools use a provider/plugin model so the same tool manages AWS, Azure, GCP, Cloudflare, Datadog, GitHub, and hundreds of other APIs through one workflow. Terraform, OpenTofu, and Pulumi are cloud-agnostic.
Cloud-native tools are built and maintained by a single cloud vendor and only manage that vendor’s resources. CloudFormation and CDK are AWS-only; Bicep and ARM templates are Azure-only; Google has Deployment Manager (now largely superseded by Terraform’s Google provider). They tend to support brand-new services on launch day and integrate tightly with the vendor’s IAM and console, at the cost of portability and a single, vendor-controlled roadmap.
HCL vs general-purpose languages
Tools also differ in how you express infrastructure.
Terraform and OpenTofu use HCL (HashiCorp Configuration Language), a declarative DSL purpose-built for describing resources. You say what you want; the engine figures out the order and the diff.
resource "aws_s3_bucket" "assets" {
bucket = "devcraftly-assets-prod"
}
resource "aws_s3_bucket_versioning" "assets" {
bucket = aws_s3_bucket.assets.id
versioning_configuration {
status = "Enabled"
}
}
Pulumi and the AWS CDK instead let you write infrastructure in a general-purpose language (TypeScript, Python, Go, C#). You get real loops, functions, classes, and your IDE’s full toolchain, but also the full weight of a programming language where a declarative config used to be.
import * as aws from "@pulumi/aws";
const assets = new aws.s3.BucketV2("assets", {
bucket: "devcraftly-assets-prod",
});
new aws.s3.BucketVersioningV2("assets-versioning", {
bucket: assets.id,
versioningConfiguration: { status: "Enabled" },
});
CloudFormation and Bicep sit in a middle lane: declarative templates (YAML/JSON for CloudFormation, a cleaner DSL for Bicep) authored for a single cloud.
The landscape at a glance
| Tool | Type | Clouds | Language | Maintainer | State model |
|---|---|---|---|---|---|
| Terraform | Provisioning | Agnostic | HCL | HashiCorp (BSL) | Explicit state file |
| OpenTofu | Provisioning | Agnostic | HCL | Linux Foundation (MPL) | Explicit state file |
| Pulumi | Provisioning | Agnostic | TS/Py/Go/C# | Pulumi Corp | Managed/self state |
| CloudFormation | Provisioning | AWS only | YAML/JSON | AWS | Service-managed |
| AWS CDK | Provisioning | AWS only | TS/Py/Go/etc. | AWS | Compiles to CloudFormation |
| Bicep / ARM | Provisioning | Azure only | Bicep DSL/JSON | Microsoft | Service-managed |
| Ansible | Config mgmt | Agnostic | YAML | Red Hat | Stateless (idempotent) |
OpenTofu and the licensing context
In 2023, HashiCorp relicensed Terraform from the open-source MPL to the Business Source License (BSL). The community responded with OpenTofu, a Linux Foundation fork that stays under the MPL and remains a drop-in replacement: the same HCL, the same providers, the same init/plan/apply workflow. For most configurations you can swap the terraform binary for tofu and everything just works.
# These are interchangeable for the vast majority of configs
terraform plan
tofu plan
Throughout this guide, anywhere you see terraform, OpenTofu’s tofu command behaves the same unless a note says otherwise.
Why this guide uses Terraform
Terraform (and by extension OpenTofu, which shares its language and ecosystem) is the default choice for a few concrete reasons:
- Reach. The provider registry covers AWS, Azure, GCP, and thousands of SaaS APIs through one consistent workflow, so the skills transfer across every cloud and vendor you will ever touch.
- Maturity. HCL is declarative and readable, the plan/apply model is battle-tested, and the module ecosystem on the public registry is enormous.
- Portability of knowledge. Learning Terraform also teaches you OpenTofu for free, and the concepts (state, providers, modules, plan diffs) map onto every other provisioning tool you might adopt later.
- Hiring and community. It is the most widely adopted IaC tool, so answers, examples, and teammates who already know it are easy to find.
If you are all-in on a single cloud and want vendor-native tooling, CloudFormation/CDK (AWS) or Bicep (Azure) are reasonable. If you strongly prefer writing infrastructure in a general-purpose language, Pulumi is excellent. For a portable, declarative skill set that works everywhere, Terraform is the safest bet, and that is what the rest of this guide teaches.
Best Practices
- Provision with Terraform/OpenTofu and configure with Ansible or pre-baked images, rather than forcing one tool to do both jobs.
- Prefer cloud-agnostic provisioning unless a vendor-only feature genuinely requires native tooling on day one.
- Standardize on one IaC tool per team; mixing Terraform and CloudFormation for the same resources invites drift and double ownership.
- Keep declarative configs declarative, reach for Pulumi/CDK only when you truly need a general-purpose language’s control flow.
- Pin tool and provider versions so
terraform/tofuproduce reproducible plans across machines and time. - Treat OpenTofu as a first-class option; its MPL license and drop-in compatibility make it a low-risk hedge against licensing changes.