🎉 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.

🔧

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