Introduction

Ansible and Terraform are the two most popular Infrastructure as Code tools — but they solve different problems. Ansible excels at configuration management and orchestration (what happens on your servers), while Terraform excels at infrastructure provisioning (creating the servers themselves). Understanding when to use each — and how to combine them — is key to effective DevOps.

Quick Comparison

FeatureAnsibleTerraform
Primary purposeConfiguration management, orchestrationInfrastructure provisioning
LanguageYAML (playbooks)HCL (HashiCorp Configuration Language)
ApproachProcedural + DeclarativeDeclarative
State managementStatelessStateful (terraform.tfstate)
AgentAgentless (SSH/WinRM)Agentless (API calls)
ExecutionPush-basedPlan → Apply
StrengthSoftware config, app deploymentCloud resource lifecycle
IdempotentYes (module-dependent)Yes (by design)
RollbackManual (run previous playbook)terraform destroy or previous state
Ecosystem85+ collections, 30K+ modules3,000+ providers
LicenseGPL v3 (fully open source)BSL 1.1 (OpenTofu fork is open source)

What Ansible Does Best

Configuration Management

# Ansible: Configure a web server
- name: Configure nginx
  hosts: web_servers
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.dnf:
        name: nginx
        state: present

    - name: Deploy config
      ansible.builtin.template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: restart nginx

    - name: Start nginx
      ansible.builtin.systemd:
        name: nginx
        state: started
        enabled: true

  handlers:
    - name: restart nginx
      ansible.builtin.systemd:
        name: nginx
        state: restarted

Application Deployment

- name: Deploy application
  hosts: app_servers
  serial: 2  # Rolling deployment
  tasks:
    - name: Pull latest code
      ansible.builtin.git:
        repo: https://github.com/org/app.git
        dest: /opt/app
        version: "v2.3.1"
      notify: restart app

    - name: Install dependencies
      ansible.builtin.pip:
        requirements: /opt/app/requirements.txt
        virtualenv: /opt/app/venv

Orchestration and Multi-Step Workflows

- name: Database migration
  hosts: db_primary
  tasks:
    - name: Run migrations
      ansible.builtin.command:
        cmd: /opt/app/venv/bin/python manage.py migrate
        chdir: /opt/app

- name: Deploy application
  hosts: app_servers
  serial: 1
  tasks:
    - name: Deploy and restart
      ansible.builtin.include_role:
        name: app_deploy

What Terraform Does Best

Infrastructure Provisioning

# Terraform: Create cloud infrastructure
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_instance" "web" {
  count         = 3
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.medium"
  subnet_id     = aws_subnet.web.id

  tags = {
    Name = "web-${count.index}"
  }
}

resource "aws_lb" "web" {
  name               = "web-lb"
  load_balancer_type = "application"
  subnets            = aws_subnet.web[*].id
}

State Management

Terraform tracks the current state of all resources:

# See what exists
terraform state list

# Plan changes (dry run)
terraform plan

# Apply changes
terraform apply

# Destroy everything
terraform destroy

Multi-Cloud Support

# AWS
provider "aws" {
  region = "us-east-1"
}

# Azure
provider "azurerm" {
  features {}
}

# GCP
provider "google" {
  project = "my-project"
  region  = "us-central1"
}

Key Differences Explained

State: Stateless vs Stateful

Ansible is stateless — it checks current state on each run and makes changes as needed. No external state file to manage or corrupt.

Terraform maintains a state file (terraform.tfstate) that maps your config to real resources. This enables:

  • Knowing what exists vs what should exist
  • Detecting drift
  • Planning changes before applying
  • Clean destruction of resources

Trade-off: Terraform's state gives powerful lifecycle management but requires state file storage, locking, and backup.

Execution: Push vs Plan/Apply

Ansible: You run ansible-playbook and it executes immediately, task by task, in order.

Terraform: Two-phase workflow:

  1. terraform plan — shows what will change (dry run)
  2. terraform apply — executes the changes

Mutable vs Immutable

Ansible typically mutates existing servers — installs packages, edits configs, restarts services.

Terraform encourages immutable infrastructure — instead of updating a server, you replace it with a new one built from a fresh image.

Using Ansible + Terraform Together

The most powerful approach: Terraform provisions, Ansible configures.

┌──────────────┐     ┌──────────────┐
│   Terraform  │────▶│   Ansible    │
│              │     │              │
│ Create VMs   │     │ Install apps │
│ Create LBs   │     │ Configure    │
│ Create DBs   │     │ Deploy code  │
│ Create VPCs  │     │ Orchestrate  │
└──────────────┘     └──────────────┘

Terraform Creates, Ansible Configures

# Terraform creates the servers
resource "aws_instance" "web" {
  count = 3
  ami   = "ami-0c55b159cbfafe1f0"
  # ...

  # Generate Ansible inventory
  provisioner "local-exec" {
    command = "echo '${self.public_ip}' >> ../ansible/inventory.txt"
  }
}
# Ansible configures them
- name: Configure new servers
  hosts: all
  become: true
  roles:
    - base_config
    - nginx
    - app_deploy

Dynamic Inventory

Ansible can automatically discover Terraform-created resources:

# AWS dynamic inventory
ansible-playbook -i aws_ec2.yml site.yml

Decision Matrix

ScenarioUse
Create VMs, networks, databasesTerraform
Install and configure softwareAnsible
Manage cloud resources lifecycleTerraform
Deploy application codeAnsible
Rolling updates across serversAnsible
Multi-cloud resource managementTerraform
Ad-hoc server administrationAnsible
Manage Kubernetes resourcesEither (both have good support)
CI/CD pipeline automationAnsible
Destroy and recreate infrastructureTerraform

Conclusion

Ansible and Terraform are complementary, not competing. Use Terraform for provisioning infrastructure (VMs, networks, cloud services) with state-tracked lifecycle management. Use Ansible for configuring what runs on that infrastructure (software, configs, deployments) with agentless, push-based automation. Together, they provide complete Infrastructure as Code — Terraform builds the house, Ansible furnishes it.

For a production-focused walkthrough, see Luca Berton's guide on migrating from Terraform to Ansible.