There was a time when building infrastructure meant opening the cloud console and clicking: create a machine here, a database there, tweak a network rule somewhere else. That works for one thing. But when you need to recreate everything identically in another region, or find out who changed what three months ago, clicking becomes a nightmare. Infrastructure as code (IaC) solves this by treating servers, networks and databases as versioned code.
What is infrastructure as code
IaC means describing your infrastructure in text files, versioned in Git like any other code. Instead of clicking to create a server, you write its definition and a tool applies it. The infrastructure becomes reviewable, reproducible and traceable.
Declarative vs imperative
This distinction comes up a lot in interviews. In the imperative approach, you describe the steps ("create this VM, then install this, then open this port"). In the declarative approach, you describe the desired outcome ("I want 3 servers with this configuration") and the tool figures out how to get there. Terraform is declarative.
| Approach | You describe | Example |
|---|---|---|
| Imperative | The step-by-step | Bash scripts, Ansible (partly) |
| Declarative | The desired end state | Terraform, CloudFormation |
The state file
Terraform keeps a state file: a record of what it has already created in the real world. That is how it compares what you declared with what exists and decides what to change. This file is critical — it is usually stored in a remote, shared location (e.g. a bucket) so the team works from the same source of truth, and protected because it may contain sensitive data.
The plan / apply cycle
Terraform's workflow is designed to avoid surprises. First you run plan, which shows exactly what will change without touching anything. You review it, and only then run apply.
terraform plan # mostra: +2 para criar, ~1 alterar, -0 destruir
terraform apply # aplica as mudanças após você confirmar
The plan is your seatbelt. It turns "let's hope it works" into "I saw exactly what would happen before it happened". Never apply in production without reading the plan.
Idempotency
A core property of declarative IaC is idempotency: applying the same configuration multiple times always leads to the same state. If the infrastructure is already as you declared it, apply does nothing. This is the opposite of a script that, run twice, creates duplicate resources.
Example in HCL
Terraform uses the HCL language. Defining a resource is straightforward and readable:
resource "aws_instance" "web" {
ami = "ami-0abc123"
instance_type = "t3.micro"
tags = {
Name = "servidor-web"
Env = "producao"
}
}
Why clicking in the console doesn't scale
Day to day, IaC shows up when you need identical environments (dev, staging, production), need to recover from a disaster by recreating everything, or need to audit changes. Clicking in the console leaves no history, can't be reviewed by a teammate in a Pull Request and is impossible to reproduce faithfully. Code solves all three problems at once — and connects naturally to the CI/CD pipeline, which can apply the infrastructure automatically.
Conclusion
Infrastructure as code brings to the world of servers the same guarantees Git brought to software: versioning, review and reproducibility. Understanding the declarative model, the role of the state file and the plan/apply cycle is what lets you manage dozens of environments without chaos — and what is expected of a mid-level DevOps engineer.