Terraform · Infrastructure as code

Why are provisioners considered a last resort?

Mediumprovisionersbootstrapanti-patternsUpdated Oct 2026
Quiz this track

Short answer

Provisioners run scripts during create or destroy and are a last resort. Prefer user_data, cloud-init, images or configuration management because provisioners are not idempotent and only run once.

A provisioner runs a command or copies a file as part of resource creation or destruction. Terraform does not track what the script did, so it cannot detect drift or rerun the script when the machine changes. That breaks the declarative model.

hcl
resource "aws_instance" "app" {
  ami           = data.aws_ami.base.id
  instance_type = "t3.micro"
  user_data     = file("cloud-init.yaml")

  provisioner "local-exec" {
    command = "echo instance-ready"
  }
}
user_data is part of the instance definition. local-exec runs on the machine running Terraform, not on the instance.

Why they cause trouble

  • They run only on create, not on every convergence
  • Failures can leave a resource tainted and half-configured
  • local-exec depends on the runner's tools and network access
  • remote-exec needs SSH or WinRM and credentials in the pipeline
  • They hide configuration outside the provider's declarative API

Use provisioners only for narrow gaps, such as registering a node with a legacy system that has no provider support. Prefer a baked image, cloud-init, a configuration-management tool, or a post-apply job with its own idempotency and retries.

A failed provisioner can mark the resource as tainted, so the next apply destroys and recreates it. That can be expensive or destructive for stateful instances.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1What is the difference between local-exec and remote-exec?
  2. 2Why is a provisioner not idempotent?
  3. 3What happens when a provisioner fails?
  4. 4How do you bootstrap an instance without a provisioner?

Say it in the interview

Provisioners run scripts at create or destroy time, but Terraform does not track their effects, so they are not idempotent and do not converge on later runs. I prefer user_data, cloud-init, baked images or a configuration-management step. When I do use one, it is a narrow gap such as a legacy registration API. I also account for the fact that a failure can taint the resource and cause a destructive replacement.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Terraform mock interview and get scored feedback on depth, clarity and confidence.