The first time I spun up a new cluster last month, Terraform spun out dozens of resources in a few minutes, then Ansible finished the job by installing the same package on every node.
Terraform provisions infrastructure resources: cloud VMs, databases, networking, and managed services. By 2019 the tool had matured enough that teams were using it for production workloads.
Because Terraform is declarative, you can review changes before they happen and repeat the same configuration in different environments without surprises.
The provider ecosystem covers AWS, Azure, GCP, Kubernetes, and hundreds of third‑party services, so you can manage everything from a single language.
One of the biggest challenges I've faced with Terraform is managing state. When you're working with a large team, it's easy to get into a situation where multiple people are trying to update the same resources at the same time. We use Terraform's built-in support for remote state stores, like AWS S3 and DynamoDB, to avoid conflicts. For example, we had a situation where two teams were trying to update the same security group rules, and it caused a lot of issues. We ended up using a DynamoDB table to lock the state file, and it solved the problem.
Ansible configures software on existing infrastructure: it installs packages, sets application settings, starts services, and deploys code to VMs.
Ansible playbooks are idempotent; running the same playbook twice ends with the same state. It pushes commands over SSH, so you never need to install an agent on the target.
In our experience, Ansible's idempotence has been a game-saver. We've had situations where a playbook would fail halfway through, and then we'd have to rerun it. With Ansible, we can just rerun the playbook, and it will pick up where it left off. For example, we were deploying a large-scale application on AWS, and one of the instances failed to provision. We simply reran the playbook, and it provisioned the instance correctly.
In production, the pattern that works is Terraform provisioning the infrastructure and Ansible configuring the software. Terraform outputs—IP addresses, DNS names, credentials—feed into Ansible inventory, keeping provisioning separate from configuration.
Packer builds machine images that already contain all the software you need. You start from a base OS image, run Ansible to install and configure everything, and produce an AMI or Azure VHD.
Deploying a new release then means replacing old instances with fresh ones booted from the new image, eliminating the need for configuration management at runtime.