Introduction#
In today’s blog post, I want to talk about a difficult decision modern DevOps teams are often facing: Terraform or Ansible?
However, I don’t want to repeat the usual answer you often hear when this question comes up — which is typically: Terraform for cloud infrastructure deployments, Ansible for day-2 configuration.
While this explanation is helpful for beginners, it becomes less useful in real-world environments. Many organizations are not only provisioning new infrastructure: They are continuously managing and standardizing existing platforms and already running systems. This is where the comparison between Terraform and Ansible becomes far more interesting.
Instead of focusing on greenfield deployments, I want to compare both tools specifically from a day-2 configuration and operations perspective.
And there is one important reality that often gets ignored in theoretical discussions: The “right” tool, of course, does not exist. It is always a personal preference.
Useful Terraform cases#
Some vendors invest heavily in Terraform providers while ignoring Ansible collections. A good example is Broadcom’s ecosystem, where significant effort is currently being placed on Terraform provider development, while Ansible integrations evolve much more slowly and mostly driven by the Broadcom community. In such cases, Terraform can become the clearly superior choice. Not because of its architecture alone, but because it offers deeper platform integration, faster feature availability, and more reliable lifecycle management.
If there is a Terraform provider from the company whose software or systems you want to configure, this is probably the best way to avoid errors, as the Terraform provider does a lot of the work for you in terms of determining which resource or configuration step needs to be performed and when.
Useful Ansible cases#
On the other hand, when teams want maximum flexibility and full control over API interactions, Ansible often becomes extremely powerful. It allows engineers to build automation workflows without waiting for vendor abstractions, and it provides the freedom to integrate any system that exposes an API.
Direct API Automation: Ansible uri vs Terraform with Terracurl#
In real-world day-2 operations, engineers often face platforms where no mature Terraform provider or Ansible collection exists, or where new features are exposed through APIs long before official integrations are updated.
In these situations, teams frequently fall back to direct HTTP automation.
Both Terraform and Ansible allow this approach, but they do so in fundamentally different ways.
Ansible uri Module – Procedural and Flexible#
Ansible provides the uri module, which allows direct HTTP calls within a playbook. This approach fits naturally into Ansible’s execution model and enables engineers to build custom workflows with API interactions.
Example:
- name: Update platform configuration
hosts: localhost
gather_facts: false
tasks:
- name: Send API request to update configuration
uri:
url: "https://api.example.com/v1/configs/app01"
method: PUT
headers:
Authorization: "Bearer {{ api_token }}"
Content-Type: "application/json"
body_format: json
body:
settingA: true
settingB: "updated"
status_code: 200
validate_certs: true
register: api_result
- name: Debug response
debug:
var: api_result.jsonEngineers have full control over:
- authentication flows
- request structure
- error handling
- loops
The automation remains procedural and explicit. Ansible does not attempt to maintain persistent state.
But: This level of control makes Ansible extremely powerful when working with unstable APIs, rapidly evolving platforms, or internal services without official tooling support.
Terraform + Terracurl – Declarative Tool Meets Imperative API Calls#
Terraform was not originally designed for manual API execution. Its strength lies in managing structured resources through providers that understand lifecycle and state.
Tools such as Terracurl attempt to bridge this gap by allowing raw HTTP requests inside Terraform workflows.
Example:
terraform {
required_providers {
terracurl = {
source = "devops-rob/terracurl"
version = "~> 1.0"
}
}
}
provider "terracurl" {}
variable "api_token" {
sensitive = true
default = "XXXXXXXXXXXXXXXXXXXX"
}
resource "terracurl_request" "update_config" {
name = "update-app01-config"
url = "https://api.example.com/v1/configs/app01"
method = "PUT"
headers = {
Authorization = "Bearer ${var.api_token}"
Content-Type = "application/json"
}
request_body = jsonencode({
settingA = true
settingB = "updated"
})
}While this works technically, it comes with a lot of difficulties:
Terraform expects resources with clear lifecycle semantics and uses declarative definitions. Terracurl executes HTTP requests that may not map cleanly to persistent infrastructure objects.
Generic API calls often produce responses that are difficult to reconcile with Terraforms state model.
As a result, Terracurl is powerful but it feels like a bad workaround when working with APIs** in comparison to Ansible.
Conclusion#
There is no universal winner between Terraform and Ansible for day-2 configuration — the deciding factor is your ecosystem. When strong, actively developed Terraform providers exist, Terraform delivers structure, lifecycle management, and long-term maintainability. When flexibility, speed, and full control over APIs matter, Ansible provides unmatched freedom.
The best teams don’t choose a side. They choose the right tool for the operational reality they face.

