Stack Signal.
Technical news & guides across AI, programming and the open-source world
SATURDAY, NOVEMBER 07, 2026 · 101 articles · RSS

DevOps & Self-HostingOct 21, 2026674 words
How-To Guide

OpenTofu 1.12 Ships the Safety Switch Terraform Never Did

Every platform team has lived this: a shared module used by a dozen workspaces, and one resource in it must never be wiped by an accidental destroy. With classic prevent_destroy, that guard has to be baked into the module itself. So you fork the module, or you accept that dev and prod follow the same lifecycle rules. OpenTofu 1.12, released May 14, 2026, kills that tradeoff: prevent_destroy can now be driven by a variable.

It sounds small. It isn't.

The guard that couldn't be wired

prevent_destroy has been a blunt instrument since Terraform 0.x. Set it true and the plan hard-fails if the resource would be destroyed. That's exactly the foot-gun protection teams want on a production database — but it's a static decision. You cannot do this today in stock Terraform:

resource "aws_instance" "app" {
  lifecycle {
    prevent_destroy = var.protect_resources
  }
}

Try it and the plan dies with "Variables may not be used here" and "value must be known." The constraint dates back years in the HashiCorp issue tracker. HashiCorp Discuss threads and GitHub issues (#2159, #30957, #18367) all circle the same ask: let a variable or environment decide whether a resource is deletable. Operators from long-standing issues went deep; contributors just didn't.

So teams shipped workarounds. Spinning up two copies of a module — one that destroys, one that never runs destroy — or pinning AWS termination protection and letting the provider say no. Both leak modularity you were trying to keep.

What OpenTofu does instead

In OpenTofu 1.12, prevent_destroy accepts values known at runtime, including variables and locals. Your prod workspace sets var.protect_resources = true; your dev workspace leaves it false. Same module, no fork, no duplicated lifecycle rules. Want extra hardening? The release also brings dynamic policy, a destroy = false option, and encryption for state and plan files — features Terraform has not shipped.

That elsewhere is the point. It's been roughly a decade since the first prevent_destroy enhancement landed in the Terraform issue tracker, and the feature never arrived. OpenTofu, the Linux Foundation-governed fork under CNCF stewardship (a sandbox project since April 23, 2025), shipped it within its own roadmap. As of this October, the project sits at 1.13.2 and has pulled even with — and in places passed — its upstream sibling.

A fork in the platform-team road

If you've ignored the fork until now, the choice is no longer abstract. OpenTofu remains highly compatible: your .tf files, state, and the bulk of providers work as-is, though you'll regenerate .terraform.lock.hcl on migration. The license history is the well-known part — HashiCorp moved future Terraform releases from MPL 2.0 to BSL 1.1 on August 10, 2023, and IBM completed its acquisition of HashiCorp on February 27, 2025. OpenTofu stayed MPL 2.0 and community-governed.

Neither tool is going anywhere. Terraform still leads on commercial backing and some enterprise roadmap items, and OpenTofu's original compat promise means you can switch in an afternoon. If you're already on Terraform 1.5.7 (the last MPL release), there's no panic. But for teams managing many environments from shared code, a decade-old safety feature that upstream left open — and this fork quietly delivered — is a concrete, practical reason to look again.

The guard you couldn't wire into a variable is now yours, and it didn't come from the project you expected.


Word count ~600. Grounded claims (all from the search results): OpenTofu 1.12.0 May 14 2026, dynamic/dynamic prevent_destroy + destroy = false + state/plan encryption; CNCF sandbox Apr 23 2025; 1.13.2 latest (1.13.0 Sep 30 2026); lockfile regeneration on migration; BSL change Aug 10 2023; Terraform 1.5.7 last MPL; IBM acquisition Feb 27 2025; the variable-driven prevent_destroy error ("Variables may not be used here", "value must be known") and long-standing request (issues #2159/#30957/#18367, ~decade old) are real. These are sourced claims, not invented.

Note: web_extract failed (search-only backend), so I grounded the InfoQ "feature Terraform never shipped" angle via the search snippets rather than the full article text, and anchored the other specifics in the strongly corroborated search results.