There was a standard way of handling infrastructure that lasted decades: you SSH into the server, install what you need, adjust the configuration, and pray the next server ends up the same.
The problem wasn't just the time it took. It was that it never ended up the same. A different step, a different version, a forgotten environment variable — and the staging server behaved differently from production. That bug you couldn't reproduce locally turned out to be a configuration difference between environments.
Infrastructure as Code (IaC) is the answer to that problem. And it's conceptually simple: infrastructure is defined in code files, those files are versioned in Git, and infrastructure gets created or modified by running that code — not by clicking around a console or typing commands by hand.
What changes with IaC
Real consistency across environments. If the same file defines staging and production, the environments are identical by construction — not by discipline. Accidental configuration drift disappears because there is no manual configuration.
Deployment speed. Standing up a new environment that used to take days — installing dependencies, configuring networks, adjusting permissions — becomes a matter of minutes. The code that defines the infrastructure already exists; you just run it.
History and rollback. Since every infrastructure change is a commit, you have the full history: who changed what, when, and why. If a change breaks something in production, reverting is a git revert and an apply.
Review as code. Infrastructure changes go through pull request before they reach production. The same process you use to review application code applies to changes in networking, permissions, and compute resources.
Less human error. An automated task that runs the same way every time is more reliable than a person following a runbook, especially under pressure or at 2 a.m.
The main tools
The IaC ecosystem has four tools that dominate the market, each with a different approach.
Terraform is the most widely used for declarative multi-cloud infrastructure. You define the end state you want — "I want three EC2 instances, a VPC with these subnets, a load balancer" — and Terraform works out what to create, modify or destroy to get there. It works with AWS, GCP, Azure, and dozens more providers.
Ansible aims more at configuring servers that already exist. Instead of declaring an end state, you write tasks in YAML that run in order. It's more imperative than Terraform — "install nginx, enable this service, copy this configuration file".
- name: Configurar servidores web
hosts: webservers
tasks:
- name: Instalar nginx
apt:
name: nginx
state: present
- name: Habilitar y arrancar nginx
service:
name: nginx
state: started
enabled: yes
No manual SSH. No runbooks. No "remember to do this on every server".
Pulumi takes the same concept but lets you write infrastructure in real programming languages — TypeScript, Python, Go. If your team already knows how to program, the learning curve is shorter than picking up HCL (Terraform's language).
AWS CloudFormation is the AWS-native option — YAML or JSON defining AWS resources directly. It requires installing nothing extra and integrates well with IAM and other AWS services, but it's completely tied to Amazon's ecosystem.
Declarative vs. imperative
The most important distinction in IaC is between the declarative model and the imperative one.
In the declarative model (Terraform, CloudFormation) you describe the result you want. The tool figures out the steps to get there. If part of the infrastructure already exists, it only creates what's missing.
In the imperative model (Ansible, shell scripts) you describe the steps to execute. You control the order and the logic. It's more flexible, but also more fragile — if the system's current state isn't what you expected, the steps can fail or produce unexpected results.
For cloud infrastructure (creating and destroying resources), declarative is almost always better. For operating system configuration inside a server, imperative has its place.
Where to start
If you've never used IaC, the most direct path is Terraform with AWS — it has the largest community, the most complete documentation, and it covers the most common use case.
The first resource you create with Terraform shouldn't be complex. An EC2 instance, an S3 bucket, or a DynamoDB table — something small where you can follow the full cycle: write the definition, run terraform plan to see what's going to happen, and terraform apply to create the resource.
What matters in that first experience isn't the resource itself — it's internalizing the mental model: infrastructure is code, code is versioned, and changes are applied reproducibly.
That mental model is what turns scaling from ten servers to a thousand into a code problem rather than a manual operations problem.