Illustration: Terraform and Ansible are not competitors The question arrives as “should we use Terraform or Ansible”, and it is the wrong shape. They solve adjacent problems and most mature environments run both.

The division that works

Terraform provisions. It talks to an API that can create resources — a cloud, a virtualization platform, a network controller — and makes reality match a declared set of objects. Its defining feature is state: it remembers what it created, so it knows what to change and what to destroy.

Ansible configures. It connects to something that already exists and brings its internal configuration to a declared state. Packages, files, services, settings.

The clean split: Terraform builds the machine, Ansible makes it useful.

Why state is the real difference

Terraform’s state file is what lets it compute a plan: here is what exists, here is what you asked for, here is the difference, here is what I will do. That plan output, reviewed before applying, is the single most valuable thing in the tool.

Ansible has no state file. It inspects the target at run time and converges. That is why it does not need to have created something in order to manage it, and why it works on the twenty-year-old server nobody has records for.

Those properties suit different jobs. State is what you want for resources you own the lifecycle of. Statelessness is what you want for a brownfield estate.

Where people go wrong

Provisioning machines with Ansible. Possible, with the cloud and virtualization modules. It works, and you lose the plan and the dependency graph and the destroy. For anything with a lifecycle, this is the wrong tool.

Configuring with Terraform. Also possible, via provisioners that run scripts on creation. The documentation itself treats these as a last resort, and it is right: a provisioner runs once at creation, does not converge, and makes the resource’s state a lie the moment anything changes.

Running Ansible from a Terraform provisioner. Common and usually a mistake. It couples the two, and it means configuration only happens at build time. Better: Terraform creates, writes the inventory or tags the resource, and Ansible runs separately against dynamic inventory.

That separation means you can re-run configuration a hundred times without touching provisioning, which is what you actually want.

The handoff

Terraform outputs. Ansible dynamic inventory reads the platform. The two do not need to talk to each other directly, and are less brittle when they do not.

Tag resources at creation with what they are, then group on those tags in inventory. A machine gets built with a role tag, and Ansible picks it up in the right group without anyone editing a file.

Where the boundary is fuzzy

Network devices. A switch is not created by Terraform and its configuration is not a package. Ansible handles this well and it is one of the places it has no real competitor.

Kubernetes objects. Both can do it, neither is ideal, and the honest answer is usually a GitOps agent instead.

Storage arrays and appliances. API-driven, and whichever tool has the better module for your specific product wins. Check before deciding on principle.

What I would actually do

If you are starting and you have an existing estate, start with Ansible, because the estate already exists and configuring it is the immediate problem.

If you are building something new on an API-driven platform, start with Terraform, because lifecycle management is the immediate problem.

Then add the other one when you hit its problem. You will.