Pulumi & the IaC landscape
Terraform is the most common IaC tool, but it isn't the only one, and a good engineer knows the landscape and the trade-offs. The central debate in IaC is whether infrastructure should be written in a purpose-built configuration language (like Terraform's HCL) or in a general-purpose programming language (like Python). This lesson maps the alternatives — especially Pulumi — and gives you a way to choose.
The two philosophies
Config-language IaC: Terraform / OpenTofu
You already know this one. You write declarations in HCL, a language built only for describing infrastructure. Its virtues are exactly its constraints:
- Simple and constrained. HCL does one thing, so configurations are easy to read and hard to over-complicate. A reviewer doesn't need to trace arbitrary program logic.
- Declarative by nature. You describe end state; loops and conditionals exist but are deliberately limited.
- Huge ecosystem. The most providers, the most public modules, the most jobs asking for it.
The downside: when you do need real logic — complex conditionals, sharing helper code, rich abstractions — HCL can feel cramped, because it isn't a full programming language.
Programming-language IaC: Pulumi (and CDK)
Pulumi takes a different bet: write your infrastructure in a real programming language — Python, TypeScript, Go, C# — using normal variables, loops, functions, and classes, with a Pulumi library that creates cloud resources. AWS's CDK (Cloud Development Kit) is the same idea, scoped to AWS (it generates CloudFormation underneath).
# Pulumi, in Python — same bucket, expressed as code
import pulumi_aws as aws
for env in ["staging", "production"]: # a real loop!
aws.s3.Bucket(f"assets-{env}",
bucket=f"my-app-assets-{env}",
tags={"env": env})
Its virtues:
- Full language power. Real loops, conditionals, functions, classes, and your existing IDE, tests, and package ecosystem. Complex logic that strains HCL is natural here.
- One language for app and infra. A team already writing TypeScript can write its infrastructure in TypeScript too — no new language to learn.
The trade-off cuts both ways: full language power means you can write infrastructure that's hard to read and reason about (arbitrary logic, side effects). The discipline HCL enforces by being limited, Pulumi leaves to you.
:::note Same engine underneath
Importantly, Pulumi is still declarative and stateful in the same way Terraform is — it has state, it does plan-like previews and apply-like updates, and it reconciles desired vs actual state. The difference is the authoring language, not the underlying model. Everything you learned about state, drift, plan/apply, and modules transfers.
:::
The cloud-native tools
Each provider ships its own first-party IaC tool, tied to that one cloud:
- AWS CloudFormation — AWS's original IaC, using YAML/JSON templates. Deeply integrated with AWS, but AWS-only and more verbose.
- Azure Bicep / ARM templates, Google Cloud Deployment Manager — the equivalents for Azure and GCP.
These can be appealing if you're committed to a single cloud and want the tightest integration. Their cost is lock-in: skills and code don't transfer to other clouds, unlike Terraform/Pulumi which are cloud-agnostic.
How to choose
A practical decision rule:
| If you... | Lean toward |
|---|---|
| Want the safe default, broadest jobs/ecosystem, cloud-agnostic | Terraform / OpenTofu |
| Have complex logic, want real loops/tests, or one language for app + infra | Pulumi (or CDK on AWS) |
| Are all-in on one cloud and want deepest native integration | That cloud's native tool (CloudFormation, etc.) |
| Are just learning IaC | Terraform / OpenTofu — it teaches the concepts cleanly and is everywhere |
:::tip Durable vs dated The config-language vs programming-language trade-off is durable — it's the real axis the whole field debates, and understanding it lets you evaluate any new tool that appears. Which specific tool is "winning," the exact feature gaps, and licensing details are dated and shift year to year. Learn the trade-off; re-check the specifics when you actually choose for a project. :::
Why it matters
The IaC landscape splits along one durable axis: config-language tools (Terraform/OpenTofu, CloudFormation) that constrain you to declarative descriptions — simpler, more reviewable, huge ecosystem — versus programming-language tools (Pulumi, CDK) that give you a full language's loops, functions, and tests at the cost of being able to over-complicate. Cloud-native tools offer the tightest single-cloud integration but lock you in. They all share the same underlying declarative, stateful, plan-and-apply model, so the concepts transfer. For most people and all learners, Terraform/OpenTofu is the right default; reach for Pulumi when real logic or a shared app/infra language matters. You've now mastered defining infrastructure as code — a checkpoint locks it in, and then Chapter 4 tackles what runs on that infrastructure at scale: containers and Kubernetes.
Next: Terraform in CI/CD →