DEV Community

Alexander
Alexander

Posted on

Terraform vs OpenTofu in 2026: I'm still on Terraform at work — and here's the honest math

TL;DR: Migrating from Terraform to OpenTofu is technically trivial. I did it this week — Terraform 1.14.7 to OpenTofu 1.11.5 — on a live AWS stack. Ten minutes, zero changes. The real question isn't can you migrate — it's when does the cost of not migrating start to hurt.

Late 2023, HashiCorp changed Terraform's license from MPL to BSL. Most of us shrugged. The change had a specific target: companies building products on top of Terraform to compete with HashiCorp. If you were using it for internal infrastructure — personal projects, company deployments, client work — the practical impact was close to zero. The panic felt overblown.

Then April 2024 arrived. IBM announced it was acquiring HashiCorp for $6.4 billion. The deal closed February 27, 2025.

Now the conversation shifts.


Why IBM changes the calculus

HashiCorp controlling BSL is one thing. IBM controlling BSL is another.

This isn't paranoia. IBM has a documented pattern. Ask anyone who ran CentOS in production. Red Hat — under IBM — ended CentOS as a stable, free downstream of RHEL without much warning. The community that had built on CentOS for years had to scramble. The argument at the time was the same: "It doesn't affect most users." Until it did.

I'm not saying IBM will change Terraform's licensing tomorrow. I'm saying the entity that now controls those decisions has shown it will prioritize enterprise revenue over community stability when the numbers make sense. That's not a character judgment — it's a business model.

OpenTofu exists precisely because the community decided not to wait and find out. It's under the Linux Foundation, MPL 2.0 licensed, with 28,000+ stars on GitHub. The governance isn't controlled by a single vendor. That matters long-term.


The migration is not the hard part

I'll be concrete. This week I set up a fresh lab to test the migration path with the latest versions of both tools. The stack: VPC with public/private subnets, S3 + CloudFront for a static frontend, API Gateway + Lambda for the backend, RDS PostgreSQL, Secrets Manager. Not a toy — a realistic serverless setup on AWS in us-west-2.

Deployed everything with Terraform 1.14.7 (released March 11, 2026 — three days ago at the time of writing). Confirmed clean state: terraform plan → "No changes." Backed up the state file. Then migrated.

It took about 10 minutes. Here's everything that happened.

1. The version constraint

First blocker: tofu init refused to run.

Error: Unsupported OpenTofu Core version

  on versions.tf line 2, in terraform:
   2:   required_version = ">= 1.14"

This configuration does not support OpenTofu version 1.11.5.
Enter fullscreen mode Exit fullscreen mode

This is the thing nobody warns you about. Terraform is on 1.14.x. OpenTofu is on 1.11.x. The version numbers diverged after the fork — each project has its own release cadence. Any required_version constraint that references Terraform's versioning will block OpenTofu.

The fix is straightforward — change >= 1.14 to >= 1.11 — but it's a decision you need to make consciously. If your repo needs to support both tools during a transition period, you'll need a constraint that covers both version tracks — something like >= 1.6 works since that's where OpenTofu forked, but it's deliberately loose. In practice, treat the constraint change as part of your migration checklist, not as a permanent state.

2. The lock file rewrite

tofu init succeeded after the version fix, but with a warning:

Warning: Dependency lock file entries automatically updated

OpenTofu automatically rewrote some entries in your dependency lock file:
  - registry.terraform.io/hashicorp/archive => registry.opentofu.org/hashicorp/archive
  - registry.terraform.io/hashicorp/aws => registry.opentofu.org/hashicorp/aws

The version selections were preserved, but the hashes were not because
the OpenTofu project's provider releases are not byte-for-byte identical.
Enter fullscreen mode Exit fullscreen mode

Two things here. First, OpenTofu rewrites the provider registry URLs automatically — registry.terraform.io becomes registry.opentofu.org. You don't have to touch your provider blocks. Second, the provider binaries aren't byte-identical between registries, so the hashes in .terraform.lock.hcl change even though the provider versions (AWS 6.36.0, archive 2.7.1) stay the same.

In a team, this matters. Once you commit the updated lock file, anyone still running Terraform against that repo will get hash mismatches. The lock file rewrite is a one-way door — plan accordingly.

3. The backend

No changes needed. My backend uses S3 with native locking — no DynamoDB:

terraform {
  backend "s3" {
    bucket       = "tf-ot-migration-lab-..."
    key          = "tf-ot-migration-lab..."
    region       = "us-west-2"
    use_lockfile = true
    encrypt      = true
  }
}
Enter fullscreen mode Exit fullscreen mode

Both Terraform 1.10+ and OpenTofu 1.10+ support use_lockfile = true for S3 native locking. If you're still on the old DynamoDB setup, the migration is the same — but it's worth noting that Terraform itself has since deprecated DynamoDB-based locking entirely. Both tools converged on the same answer — DynamoDB was always a workaround, not a solution.

4. The plan

tofu plan
...
No changes. Your infrastructure matches the configuration.
Enter fullscreen mode Exit fullscreen mode

Zero diff. OpenTofu 1.11.5 read the state file written by Terraform 1.14.7, compared it against the same HCL, refreshed every resource, and found nothing to change. Same VPC, same subnets, same CloudFront distribution, same Lambda, same RDS instance. Every resource ID matched.

5. The apply

tofu apply
...
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Enter fullscreen mode Exit fullscreen mode

The apply updated the state file metadata — terraform_version changed from "1.14.7" to "1.11.5", serial incremented from 6 to 7. State format stayed at version 4. No infrastructure touched.

That's the whole migration. Ten minutes, one version constraint edit, one lock file commit.

6. The proof: a real change

To confirm OpenTofu had full control of the stack, I made one intentional change — updated the ManagedBy tag from "terraform" to "OpenTofu" across all resources:

tofu plan
...
Plan: 0 to add, 18 to change, 0 to destroy.
Enter fullscreen mode Exit fullscreen mode

Every resource in the stack picked up the tag change. Nothing else moved. tofu apply — 18 changed, zero surprises. OpenTofu is now managing the infrastructure, not just reading the state.

7. The HCL itself

Nothing changed beyond the tag value and the version constraint. Resources using count, for_each, locals with merge() for common tags — all fully compatible. No Terraform Cloud features, no check blocks. The infrastructure code was untouched.


Why I haven't migrated at work

Here's the part most articles skip because it makes the narrative less clean.

I'm the bus factor on the IaC side of my current project. One person who understands the full state of the infrastructure, the module structure, the pipeline configuration. In that context, migrating is a risk I'm choosing not to take right now — not because migration is hard, but because I have deliverables that matter more than tooling hygiene at this moment.

The math is simple: migration adds zero business value to what I need to deliver in the next 8 weeks. It introduces a non-zero chance of something going sideways in a pipeline that's working. That's a bad trade.

This isn't loyalty to Terraform. It's prioritization.

The calculation changes when:

  • Starting a new project with no existing state
  • Working with a client who has no lock-in to Terraform Cloud or TF Enterprise
  • The team has bandwidth to absorb the change and test thoroughly
  • The pipeline dependencies (CI/CD, state backend, module registry) can be updated cleanly

For greenfield work today, I'd choose OpenTofu by default. The licensing risk is lower, the features are better, and the governance model is more trustworthy long-term.


What OpenTofu has that Terraform doesn't

These aren't marketing features. They're things that solve real problems.

State encryption (1.7)

Native, client-side encryption for state files. No external KMS required. Your state — which contains sensitive values like database passwords, private keys, and resource IDs — gets encrypted before it ever leaves your machine or CI runner.

terraform {
  encryption {
    key_provider "pbkdf2" "main" {
      passphrase = var.state_passphrase
    }
    method "aes_gcm" "main" {
      keys = key_provider.pbkdf2.main
    }
    state {
      method = method.aes_gcm.main
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Terraform has no equivalent. If you're storing state with sensitive data in S3 and relying on bucket encryption + IAM, that's a different threat model than encrypting the content before it's stored. For compliance requirements — and there are a lot of them in regulated industries — this matters.

Early variable evaluation (1.8)

Variables can now be referenced in backend configuration — something that previously wasn't possible without workarounds. The typical solution was Terragrunt or wrapper scripts to inject dynamic values at init time.

I don't use Terragrunt. My current setup uses tfvars per environment with pipeline logic handling account selection at runtime. That works. But if your team is running Terragrunt purely to pass variables to the backend, this feature removes that dependency entirely.


The honest recommendation

For new projects: OpenTofu. The migration cost is zero, the governance is better, and the feature trajectory is ahead of Terraform's open-source track.

For existing production: evaluate your specific situation. The questions that matter:

  • Are you using Terraform Cloud or TF Enterprise features?
  • Is your team at capacity, or do you have bandwidth for a migration sprint?
  • Do you have downstream tooling (Atlantis, Spacelift, custom pipelines) that needs updated configuration?

If the answers are "no, yes, and no" — migrate. If not, plan it, don't rush it.

The CentOS analogy isn't perfect. IBM might leave Terraform's licensing untouched for years. But "it might be fine" is not a risk management strategy. OpenTofu gives you a way out that doesn't require scrambling later.

I'll take the clean exit while it's still calm.


Migration tested March 2026: Terraform 1.14.7 → OpenTofu 1.11.5, AWS provider 6.36.0, S3 backend with native locking. Full stack: VPC, S3, CloudFront, API Gateway, Lambda, RDS, Secrets Manager. Zero breaking changes. Check the official migration guide before applying to production.

Top comments (0)