Terraform vs Ansible: Infrastructure as Code Tools Compared
Terraform and Ansible show up together in almost every "IaC tools" list, which leads a lot of people to assume they're interchangeable competitors. They're not. They solve genuinely different problems, and most real-world setups use both.
What Infrastructure as Code actually means
Before comparing tools, it's worth being precise about the underlying idea: instead of manually clicking through a cloud console or SSHing into servers to make changes, you describe your desired infrastructure in code, check it into version control, and let a tool apply it. This gets you the same benefits software engineering already has: code review, history, repeatability, and the ability to recreate an entire environment from scratch.
Terraform: provisioning
Terraform's job is provisioning, creating, updating, and destroying infrastructure resources themselves: virtual machines, networks, load balancers, DNS records, managed databases, Kubernetes clusters. You describe what should exist, in HashiCorp Configuration Language (HCL), and Terraform figures out the API calls needed to make it real.
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "web-server"
}
}
Terraform is declarative: you describe the end state, not the steps to get there. It's also stateful: Terraform keeps a state file recording what it believes exists, and compares that against your configuration on every run to compute a plan (terraform plan) of exactly what will change before touching anything (terraform apply).
Key concepts:
- Providers: plugins that let Terraform talk to a specific platform's API (AWS, Azure, GCP, Kubernetes, even SaaS tools like Datadog or GitHub).
- State: a record of managed resources; for teams, this is stored remotely (e.g., in S3 with locking) so multiple people don't clobber each other's changes.
- Modules: reusable, parameterized bundles of resources, so you're not copy-pasting the same VPC configuration across every project.
- Drift detection: because Terraform compares real infrastructure against its state on every plan, it can detect when someone made a manual change outside of Terraform (drift), a common real-world headache.
Ansible: configuration management
Ansible's job is configuration management: once a server exists, what software gets installed on it, what users exist, what config files look like, what services are running. Ansible connects over SSH (no agent needs to be installed on target machines) and executes tasks defined in YAML "playbooks."
- name: Configure web servers
hosts: webservers
become: true
tasks:
- name: Install nginx
apt:
name: nginx
state: present
- name: Start nginx
service:
name: nginx
state: started
enabled: true
Ansible playbooks are designed to be idempotent: running the same playbook twice should produce the same result and not duplicate work the second time. The state: present above means "make sure nginx is installed," not "install nginx." If it's already there, Ansible does nothing.
Key concepts:
- Inventory: a file (or dynamic source) listing target hosts, often grouped (webservers, dbservers).
- Playbooks: YAML files defining ordered tasks against a group of hosts.
- Roles: a way to package related tasks, files, and templates for reuse, similar in spirit to Terraform modules.
Where they overlap, and where they don't
It's genuinely common to use both together: Terraform provisions the VMs, networking, and managed services; Ansible then configures the software running on those VMs. Terraform can run limited provisioning-time scripts, and Ansible does have cloud modules for creating resources, but each is noticeably less mature at the other's core job: using Terraform for configuration management or Ansible as your primary provisioning tool usually means fighting the tool.
| Terraform | Ansible | |
|---|---|---|
| Primary job | Provisioning infrastructure | Configuring software on existing machines |
| Paradigm | Declarative, stateful | Procedural-ish, agentless, idempotent |
| Language | HCL | YAML |
| Needs an agent? | No (talks to cloud APIs) | No (uses SSH) |
A common interview question: declarative vs. imperative
Terraform is declarative: you say what you want, not the steps to get there, and the tool figures out the diff. A purely imperative approach would instead require you to write out every step ("create this VM, then attach this disk, then..."). That gives more control, but no automatic reconciliation against current state. Ansible sits in between: playbooks read like ordered steps, but individual tasks are idempotent, so re-running is safe.
Getting started
If you're new to IaC, a practical learning path is: provision a single VM with Terraform, then write a small Ansible playbook to install and configure a web server on it. That one exercise touches almost every core concept from both tools.
Test your knowledge with the Infrastructure as Code quiz on OpsQuiz.