🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

Terraform null_resource Deprecated Warning — What to Use Instead

Terraform's null_resource is deprecated in favor of terraform_data. Learn what changed, how to migrate your existing null_resource blocks, and common patterns that now have better native solutions.

Shubham3 min read
Share:Tweet

If you've run terraform plan recently on an older codebase and seen this warning:

Warning: Deprecated resource
  null_resource has been deprecated in favour of terraform_data.
  Please update the resource type from null_resource to terraform_data.

You're not alone. The null_resource that everyone's been using for years for local-exec provisioners and depends_on tricks is being replaced.

Here's what changed and how to migrate.

What Was null_resource Used For?

null_resource has always been a workaround — a resource that does nothing on its own but lets you attach provisioners and triggers to it.

Common patterns:

  • Running local scripts or commands after a resource is created
  • Forcing re-runs when certain values change (triggers)
  • Creating explicit depends_on relationships that aren't captured by resource references
hcl
# Old pattern with null_resource
resource "null_resource" "run_migration" {
  triggers = {
    always_run = timestamp()
  }
 
  provisioner "local-exec" {
    command = "kubectl apply -f migrations/"
  }
 
  depends_on = [aws_eks_cluster.main]
}

The Replacement: terraform_data

terraform_data is a built-in resource (available since Terraform 1.4) that replaces null_resource without requiring the hashicorp/null provider.

The migration is mostly a find-and-replace:

hcl
# New pattern with terraform_data
resource "terraform_data" "run_migration" {
  triggers_replace = [timestamp()]  # Note: triggers_replace, not triggers
 
  provisioner "local-exec" {
    command = "kubectl apply -f migrations/"
  }
 
  depends_on = [aws_eks_cluster.main]
}

Key differences:

  • triggers becomes triggers_replace
  • No provider required (terraform_data is built in)
  • The input and output attributes let you store and reference values

Migration Guide

Pattern 1: Triggers Map → triggers_replace

hcl
# Before
resource "null_resource" "example" {
  triggers = {
    cluster_id = aws_eks_cluster.main.id
    config_hash = md5(file("config.yaml"))
  }
}
 
# After
resource "terraform_data" "example" {
  triggers_replace = [
    aws_eks_cluster.main.id,
    md5(file("config.yaml"))
  ]
}

Note: triggers_replace is a list, not a map. If you were using the trigger key names in your provisioner commands, you'll need to adjust.

Pattern 2: Storing Values with input/output

terraform_data has an input attribute that stores arbitrary values, accessible via output:

hcl
resource "terraform_data" "bootstrap" {
  input = {
    cluster_endpoint = aws_eks_cluster.main.endpoint
    cluster_name     = aws_eks_cluster.main.name
  }
 
  provisioner "local-exec" {
    command = "aws eks update-kubeconfig --name ${self.output.cluster_name}"
  }
}
 
# Reference the output elsewhere
output "cluster_info" {
  value = terraform_data.bootstrap.output
}

This is more powerful than null_resource's triggers, which could only store values for trigger purposes.

Pattern 3: depends_on — No Change

hcl
# This works exactly the same
resource "terraform_data" "wait_for_cluster" {
  depends_on = [
    aws_eks_cluster.main,
    aws_eks_node_group.workers
  ]
 
  provisioner "local-exec" {
    command = "sleep 30 && kubectl get nodes"
  }
}

When null_resource Actually Makes Sense Still

The null_resource isn't removed — just deprecated. You can keep using it if:

  • You're on Terraform < 1.4 (terraform_data isn't available)
  • You have a massive codebase and can't migrate everything at once
  • Your organization hasn't upgraded the null provider and you don't want to add a new dependency

The deprecation warning won't cause your plans to fail. It's just a warning.

Better Alternatives to Both

For some null_resource use cases, there are better native solutions in modern Terraform:

Running post-deployment scripts: Consider using local-exec provisioners on the actual resource instead of a separate null_resource.

Waiting for resources: Use timeouts blocks on resources that support them, or the terraform_data with a sleep command.

Complex dependencies: If you're using null_resource purely for depends_on, check if you can express the dependency through resource references directly — Terraform tracks these automatically.

Fixing the Warning in CI

If your CI pipeline fails on warnings, add this to suppress during migration:

bash
TF_CLI_ARGS_plan="-no-color" terraform plan 2>&1 | grep -v "Warning: Deprecated"

But the right fix is migration. In most codebases, replacing null_resource with terraform_data is a 5-minute change per occurrence.


More Terraform troubleshooting? Check our Terraform state lock error fix and Terraform plan unexpected destroy fix.

Did this fix work?

Tell us what needs improving. No account required.

🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments