Declarative provisioning for cloud resources, the canonical Infrastructure as Code system. Write resources in HCL, run terraform plan to diff the desired state against a persisted state file, then terraform apply to execute the explicit plan of API calls. The model is closed-world: anything not in the config is unmanaged or, if previously managed, will be destroyed.

The plan/apply split is the feature. Most infrastructure mistakes are not “I wrote the wrong thing,” they are “I didn’t realize this change would also destroy that thing.” terraform plan makes the blast radius visible before commit, which is qualitatively different from procedural tools that only reveal effects by running. The state file is the trade-off. It must be stored somewhere durable (S3, Terraform Cloud, GCS), locked during writes, and treated as sensitive (it can contain plaintext secrets).

Sweet spots are cloud infrastructure (VMs, VPCs, IAM, DNS, S3) and app-level “API objects” via providers like Grafana, Keycloak, and GitHub org settings. Anti-patterns: managing relational schema via Terraform (destroy-and-recreate semantics are catastrophic for tables with data; use Atlas (Schema as Code) instead), and null_resource + local-exec to bolt imperative steps onto a declarative graph.

If you’re asking “will this remove things I didn’t mean to remove?” you want Terraform’s plan step. If you’re asking “how do I get Terraform to just run this one command?” you want Ansible. Don’t co-manage the same object with two tools. Pick one owner per resource or live with permanent drift loops. Terraform’s BUSL relicense in August 2023 forked OpenTofu as a community-governed alternative. Wire-compatible for now, but they will diverge.