What Is Infrastructure as Code
The idea in one sentence
Section titled “The idea in one sentence”Infrastructure as Code means describing your cloud resources in a text file that lives in version control, instead of clicking through a console — the file is the source of truth, and a tool reconciles reality to match it.
The problem with ClickOps
Section titled “The problem with ClickOps”Picture an engineer opening the Google Cloud console and creating a VPC network, a couple of subnets, a Compute Engine VM, and a firewall rule by hand. It works. Then three weeks later someone else opens the console, tweaks a firewall rule to unblock a deploy, and never tells anyone. A month after that, someone deletes what looks like an orphaned Cloud Storage bucket — it was not orphaned.
This pattern has a name, usually said with a grimace: ClickOps. The failure mode is not that any single click was wrong. It is that the sequence of clicks is:
- Unrepeatable — nobody can stand up an identical environment from scratch, because the “instructions” were a person’s muscle memory.
- Undocumented — the console shows the current state, not why it looks that way or who changed what.
- Drift-prone — the moment two people can independently change the same project, the project’s real state and anyone’s mental model of it start to diverge, silently.
Nobody can answer “what is actually deployed right now, and why” just by reading anything. The console itself is the only source of truth, and it has no memory, no review process, and no diff.
Declarative versus imperative
Section titled “Declarative versus imperative”Infrastructure as Code (IaC) fixes this by making the desired infrastructure a file: checked into git, reviewed in a pull request like any other code change, with history you can git blame. But not all IaC tools work the same way, and the distinction matters:
- Declarative IaC — you describe the end state you want, and the tool figures out how to get there. Terraform is declarative: a
resourceblock says “there should be a storage bucket named this, with these properties,” and Terraform works out whether that means creating it, updating it, or leaving it alone. - Imperative IaC — you write an ordered script of steps: “create a VPC network, then create a subnet inside it, then launch an instance in that subnet.” The script describes how, and it is your job to keep it correct as things change; running it twice can misbehave unless every step is written to be safe to repeat.
# Declarative: describe the desired end state.# Terraform decides what needs to change to get there.resource "google_storage_bucket" "reports" { name = "acme-monthly-reports" location = "US"}# Imperative equivalent: an explicit, ordered command.# Running this twice creates two buckets (if the name were unique)# or errors out — the script itself has no idea what already exists.gcloud storage buckets create gs://acme-monthly-reports --location=USNotice the declarative version never mentions create. That verb is decided by Terraform, at plan time, based on what it finds.
How Terraform reconciles state
Section titled “How Terraform reconciles state”Terraform’s core loop is always the same three-way comparison:
- Read the current real-world state of the resources it manages (it keeps a record of this in a state file).
- Read your declared configuration — the HCL describing what you want.
- Compute a plan: the minimal set of creates, updates, and destroys needed to make the real world match the configuration.
Nothing gets torn down and rebuilt from scratch just because you changed one argument. If you only changed a VM’s labels, the plan is an in-place update to that one attribute — everything else Terraform manages is left untouched.
flowchart LR config["HCL config (desired state)"] --> tf["Terraform"] real["Real GCP resources (actual state)"] --> tf tf --> plan["Plan: the diff"] plan --> apply["Apply: minimal changes"]
Where Terraform fits
Section titled “Where Terraform fits”Terraform is not the only IaC tool, and it helps to know what it is not:
- Google Cloud Deployment Manager — GCP’s original declarative IaC tool, using YAML templates (optionally extended with Python or Jinja2), but GCP-only. There is no equivalent way to manage an AWS account or a Datadog monitor from the same template, and Google now steers new projects toward Infrastructure Manager, a managed service that runs Terraform configurations directly rather than a separate templating language.
- Pulumi — also provider-based and state-tracked, but you write actual programming languages (TypeScript, Python, Go) instead of a declarative HCL syntax, trading a smaller learning curve for the full expressiveness (and full complexity) of a general-purpose language.
- Ansible — primarily a configuration management tool: it logs into existing machines and runs tasks against them (install a package, edit a config file, restart a service). Its playbooks are closer to imperative in practice — ordered tasks executed top to bottom — and it has no built-in state file tracking what it created.
Terraform’s niche is declarative, provider-based, state-tracked infrastructure provisioning: a plugin model (providers) lets the same workflow and HCL syntax target GCP, AWS, Azure, Kubernetes, Datadog, and hundreds of other systems, with a state file recording exactly what Terraform is responsible for.
One more name worth knowing: OpenTofu. After a 2023 licensing change to Terraform, a group of contributors and companies forked the last open-source release into OpenTofu, now maintained under the Linux Foundation. It is a compatible, open-source alternative — the HCL syntax, providers, and workflow you learn here apply to it directly.