OpenTofu vs Terraform. Should I switch?


Terraform isn’t MPL anymore. OpenTofu is the community fork. If you’re responsible for a Terraform codebase you probably want a considered answer to “should I switch.” Here is mine.

What actually happened

Quick recap, with as little drama as possible:

That is the entire substance of the “drama.” The boring practical question is whether the syntax you already write still works.

The practical answer

For almost everyone the answer is: yes, both still work, OpenTofu is a drop-in replacement, you can switch the binary and your code is fine. I have done the switch on two reasonable-sized codebases. Both times it went like this:

$ brew install opentofu       # or whatever your package manager is
$ tofu init
$ tofu plan
$ tofu apply

That is the migration. The state file format is compatible. terraform_remote_state still works. Modules from the registry still install. The same providers from registry.terraform.io can be used, and OpenTofu also has its own registry at registry.opentofu.org mirroring most of them.

The minor wrinkle is the binary name. tofu instead of terraform. If you have CI scripts or developer workflows hardcoded to terraform plan, that’s a search-and-replace. Some teams alias terraform to tofu on shared runners during the transition. That works, but I would rather rip the band-aid off.

Should you switch?

The reasons to switch:

The reasons not to switch:

Running both

You don’t actually have to choose. The two binaries can operate on the same code, sometimes even on the same state, as long as you avoid features that exist in only one of them. I have a small CI matrix on one project that runs terraform fmt -check and tofu fmt -check, and terraform validate and tofu validate, as a smoke test. It catches accidental drift.

jobs:
  lint:
    strategy:
      matrix:
        tool: [terraform, tofu]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
        if: matrix.tool == 'terraform'
      - uses: opentofu/setup-opentofu@v1
        if: matrix.tool == 'tofu'
      - run: ${{ matrix.tool }} fmt -check -recursive
      - run: ${{ matrix.tool }} validate

What I actually do

I run OpenTofu locally and in CI for everything new. I have not migrated a couple of older systems that are tied to a Terraform Cloud workspace. I don’t feel any urgency about it. The point of infrastructure-as-code was always that the code was the durable artifact, not the binary that interprets it.

The thing I would not do is wait for the dust to settle. The dust has settled. OpenTofu is here, it is fine, the licensing is clean. If you have a quiet afternoon, switch and stop thinking about it.