Terraform vs Ansible: Provisioning vs Configuration
Terraform and Ansible solve different infrastructure problems: declarative provisioning versus procedural configuration. When to use each, and when to use both.
Terraform and Ansible are both infrastructure automation tools, but they solve different problems and are often used together rather than as substitutes for each other. Terraform is a declarative provisioning tool — it creates and manages the cloud resources themselves. Ansible is a procedural configuration tool — it logs into machines that already exist and gets them into a desired state. Confusing the two is one of the most common mistakes teams make when they’re new to infrastructure as code.
What each tool is actually for
Terraform describes what should exist: a virtual machine, a load balancer, a managed database, a DNS record, a whole VPC. You write infrastructure as code in HashiCorp Configuration Language describing the end state, Terraform compares that to a state file recording what it last created, and it computes a plan — resources to add, change, or destroy — to reconcile the two.
Ansible describes what should be installed and configured on machines that already exist. It connects over SSH (or WinRM), runs a sequence of tasks — install this package, template out this config file, restart this service — and applies them to a list of target hosts. There’s no separate resource model or persistent state file the way Terraform has one; Ansible just executes tasks against the hosts you point it at, each run.
Declarative versus procedural
This is the deepest difference between them, and it’s worth being precise about.
Terraform is declarative in a strong sense: you describe the desired end state, and Terraform’s provider plugins figure out the sequence of API calls needed to get there, tracking what already exists in its state file so it only changes what’s actually different. Run the same Terraform configuration twice and, assuming nothing drifted outside of Terraform, the second run does nothing.
Ansible is procedural with declarative tasks: each task in a playbook typically describes a desired state (“this package should be installed,” “this file should have this content”) and is idempotent on its own — running it twice doesn’t reinstall the package a second time — but Ansible doesn’t track an overall desired-state model across runs the way Terraform’s state file does. It just runs the playbook, top to bottom, checking each task’s own condition as it goes.
Agent-based versus agentless
Ansible is agentless: it connects over standard SSH and pushes Python (or PowerShell) to run remotely, so there’s no persistent daemon to install, patch, or secure on the target hosts. This is one of its most-cited advantages over configuration tools that do require an installed agent.
Terraform doesn’t have an “agent” in the same sense, because it isn’t managing the internals of a running machine — it’s talking to cloud provider APIs (or a Kubernetes API, or any other system with a Terraform provider) to create and destroy resources. The distinction that matters more for Terraform is its state file: a persistent record of what it created, which must be stored somewhere durable and shared safely across a team, since state corruption or drift between the file and reality causes real problems.
Side-by-side comparison
| Terraform | Ansible | |
|---|---|---|
| Primary job | Provision cloud/infra resources | Configure existing machines |
| Model | Declarative, with tracked state | Procedural, idempotent tasks |
| State tracking | Persistent state file | None — evaluates live state each run |
| Connection model | Cloud provider APIs | Agentless, over SSH/WinRM |
| Typical scope | VMs, networks, managed services, DNS | OS packages, config files, services, deployments |
| Drift handling | Detects and can revert drift from state | Re-applies tasks; doesn’t track “should not exist” |
Where they overlap, and where teams get confused
Both tools can touch adjacent territory — Terraform has provisioners that can run remote scripts after creating a resource, and Ansible has cloud modules that can create VMs or load balancers. In practice, most teams find that using each tool for its strong suit and avoiding the overlap keeps things simpler: let Terraform own everything that maps to a cloud resource, and let Ansible own everything that happens inside a running machine once it exists.
A common pipeline looks like this: Terraform provisions the VM, network, and security group; its output (an IP address, typically) feeds into an Ansible inventory; Ansible then connects to that IP and installs the application stack. Neither tool replaces the discipline of GitOps or the goal of immutable infrastructure — many teams that adopt containers and immutable machine images use Terraform alone and lean on Ansible only for bootstrap tasks, or drop it entirely in favor of baking configuration into the image itself.
Drift is where the philosophies diverge most
Because Terraform tracks state, it can detect infrastructure drift — a resource manually changed outside of Terraform — and offer to revert it back to the declared configuration. Ansible has no equivalent concept of “this should not exist”; a playbook enforces the tasks it’s given but has no memory of a previous run to compare against, so accidental manual changes on a server only get corrected if a task explicitly checks for and fixes that exact condition.
When to use which
- Provisioning cloud resources, however small the scope — reach for Terraform. Its plan-before-apply workflow and state tracking make it safer for anything that costs money or affects other systems.
- Configuring software on servers you don’t want to bake into an image — reach for Ansible. It’s lightweight, agentless, and well suited to ad hoc automation across a fleet of existing hosts.
- A twelve-factor containerized stack on Kubernetes — you may not need Ansible at all; Helm charts and Terraform’s Kubernetes provider often cover the whole surface.
The takeaway
Terraform and Ansible aren’t really competitors — Terraform provisions the infrastructure that Ansible then configures, and most production pipelines that use both keep that boundary clean. Reach for Terraform when the question is “what resources should exist,” and reach for Ansible when the question is “what should be installed and running once they do.” Trying to make one tool do the other’s job usually costs more in complexity than it saves in tooling.
Tagged
Keep reading
Chisato · · 5 min read Multi-Cloud vs Hybrid Cloud: The Real Difference
Multi-cloud spreads workloads across public cloud providers; hybrid cloud connects private infrastructure to a public cloud. How they differ and why it matters.
Chisato · · 4 min read Immutable Infrastructure, Explained
Immutable infrastructure replaces servers instead of patching them in place — every change ships as a new, versioned artifact. How it works and why.
Chisato · · 3 min read What Is a Runbook? Incident Response Playbooks
A runbook is a step-by-step document for handling a specific operational task or incident, turning tribal knowledge into a repeatable procedure.