# OpenTofu 1.13 Makes Infrastructure Plans More Precise

- Link: https://thestackobserver.com/opentofu-1-13-makes-infrastructure-plans-more-precise/
- Published: 2026-10-16T08:01:41-04:00
- Author: Stackxx

Infrastructure plans are valuable only to the extent that they describe the change
an automation system will actually make. OpenTofu 1.13 attacks one of the least 
glamorous but most consequential gaps in that promise: values that remain unknown
until apply. Its new `convert` and `assume...` functions let module authors add 
information the engine cannot infer on its own, potentially making plans more useful
to reviewers, policy engines, and downstream modules.

The release, published September 29, is deliberately smaller than some earlier OpenTofu
updates. The project shortened its development cycle to align more closely with 
Go releases and extend the series’ security-support window through August 2027. 
That makes the planning changes easy to underestimate. They are not flashy syntax
for its own sake. They recognize that infrastructure-as-code governance depends 
on the quality of information available _before_ a change reaches production.

**The central lesson for platform teams is straightforward:** OpenTofu 1.13 can 
reduce avoidable uncertainty in plans, but it does so by asking module authors to
take explicit responsibility for claims about future values. That trade is useful
when guarantees are real and dangerous when assumptions are merely hopeful.

## Why unknown values create operational friction

OpenTofu builds a dependency graph and predicts changes during planning, but providers
often cannot know an attribute until an API creates or updates a remote object. 
The familiar `(known after apply)` marker is an honest representation of that limit.
An ID allocated by a cloud service, for example, may not exist yet.

Unknown does not always mean that every property of a value is unknowable, however.
A provider may not know the future VPC ID, while its API contract still guarantees
that the ID will be a non-null string beginning with `vpc-`. Historically, that 
distinction could be lost. Expressions that compare the ID with null, validate its
prefix, or use its presence to enable another component could themselves become 
unknown.

The consequences spread beyond untidy console output. OpenTofu currently requires
some decisions, including those involving `count`, `for_each`, and `enabled`, to
be resolvable during planning. Unknown data can therefore block a configuration 
even when a human understands the future value’s constraints. Machine-readable plans
pose another problem: a policy engine encountering an unknown field must either 
permit a change it cannot fully evaluate or reject a change that might be compliant.

This is the boundary OpenTofu 1.13 tries to sharpen. The engine still will not invent
remote API results. Instead, module authors can preserve facts they know about those
results so that subsequent expressions have more information to work with.

## `convert` carries type information through the plan

The new `convert` function allows an author to declare the expected type of an expression
whose structure cannot otherwise be predicted. The project’s example starts with
dynamic JSON. Passing an unknown string to `jsondecode` normally yields a result
with an unknown type as well as an unknown value. If the producer’s contract guarantees
a particular schema, `convert` can describe it as an object with fields such as 
a string ID and a map of tags.

The decoded value does not magically become known. OpenTofu still cannot display
the future ID or tags. But it now knows that accessing the ID will produce a string
and that the tags field is a string map. That distinction can allow type checking,
expression evaluation, and module composition to progress further during planning.

For platform engineers, the practical use case is a shared module sitting between
a resource provider and many application stacks. Instead of forcing every consumer
to rediscover or work around an imprecise result type, the shared module can encode
the producer’s documented contract once. Consumers then receive a more useful interface
without coupling themselves directly to provider quirks.

Teams should treat such conversions as interface declarations, not convenient casts.
The declared object type belongs in the same review category as a module variable
schema or an API definition. If the upstream producer changes shape, the conversion
can fail. That is preferable to silent corruption, but it still moves a possible
error from plan time to apply time unless the contract is tested elsewhere.

## The `assume...` family records value constraints

Where `convert` describes type, the `assume...` functions add facts about the value
itself. OpenTofu documents examples including a value being non-null or a string
having a known prefix. Wrapping a future VPC ID with `assumenotnull` and `assumestringprefix`
can let downstream logic prove that comparisons with null or an empty string are
false. Validation expecting `vpc-` may also run during planning rather than waiting
for apply.

This feature shifts the location of knowledge. Providers remain the ideal place 
to expose accurate plan-time semantics because they sit closest to the remote API.
Yet provider schemas do not always capture every guarantee, and fixes may arrive
slowly. A carefully maintained module can now bridge that gap for its consumers.

The word _assume_ is an important warning label. If an author promises a `vpc-` 
prefix and the service returns `subnet-`, OpenTofu will fail the assumption during
apply. The result is not a loophole around reality; it is a runtime assertion. Platform
teams gain a more precise plan only by accepting responsibility for the assertion’s
accuracy.

## A safe adoption playbook for module owners

The best first targets are established contracts that are already documented and
stable. Do not scatter assumptions through root configurations just to eliminate
every unknown marker. Centralize them at the narrowest reusable boundary where the
team owns the abstraction.

### 1. Inventory uncertainty that changes decisions

Start with unknowns that prevent a plan, blind a policy check, or cause downstream
module interfaces to lose useful type information. Cosmetic unknowns that do not
affect review or execution are poor candidates. This keeps the feature focused on
measurable developer-experience and governance problems.

### 2. Identify the source of truth

For every proposed conversion or assumption, cite the provider documentation, vendor
API contract, or an internally controlled schema that makes the claim reliable. 
A value that merely _usually_ has a prefix is not equivalent to a guaranteed prefix.
If no durable source exists, leave the value unknown and pursue a provider improvement
instead.

### 3. Encapsulate the assertion

Place the new function in the shared module that already abstracts the resource 
or data source. Expose the refined result as a typed output. This avoids duplicating
assumptions across repositories and creates one place to update when an upstream
contract changes.

### 4. Test both plan and apply paths

A regression suite should prove that the refined information produces the intended
plan-time result and that a representative apply satisfies the assertion. Include
negative tests where feasible. If a module claims a JSON object shape, test missing
and changed fields; if it claims a prefix, test the failure behavior operators will
see.

### 5. Measure the governance effect

Compare policy results before and after adoption. The goal is not a plan with zero
unknowns. It is fewer indeterminate decisions, fewer unnecessary policy denials,
and earlier feedback on genuinely invalid configurations. Record which policies 
still need explicit unknown-value handling because no safe assumption is available.

## What else changes the upgrade calculation

Teams evaluating 1.13 should separate the planning opportunity from several compatibility
changes. The release removes WinRM connections for `remote-exec` and `file` provisioners
after deprecating them in 1.12; configurations using `type = "winrm"` must move 
to OpenSSH for Windows before upgrading. OpenTofu on macOS now requires macOS 13
Ventura or later, and 1.13 is the final series with official 32-bit builds.

The `base64gzip` function also produces compressed data that is equivalent after
decompression but not byte-for-byte identical to earlier output because of an upstream
Go implementation change. If that output feeds a managed resource argument, a post-
upgrade plan may propose an update or replacement. Review those plans closely; the
project suggests temporary `ignore_changes` usage when a team cannot immediately
accept the new representation.

Windows on ARM64 gains official OpenTofu packages, although third-party provider
availability still depends on each provider maintainer. The release also previews
experimental built-in linting and Symbol Libraries. Those experiments signal a broader
interest in bringing reusable logic and earlier feedback closer to the core language,
but they should not be treated as stable production dependencies yet.

## More precise plans require stronger module governance

OpenTofu 1.13 does not eliminate plan-time uncertainty, nor should it. Cloud APIs
remain dynamic, and a plan that fabricates certainty would be worse than one that
clearly marks what it cannot know. The release instead creates a vocabulary for 
facts that exist outside the engine’s current inference.

That makes module ownership more important. A central platform team can use these
functions to publish sharper contracts and help policy systems decide earlier. The
same team can also create brittle applies if it encodes undocumented behavior as
guaranteed truth. Code review should therefore ask two questions for each assumption:
_Who guarantees this fact?_ and _How will we detect when it stops being true?_

Used with that discipline, the new functions can improve infrastructure delivery
in a subtle but meaningful way. They move feedback left without pretending the future
is fully knowable. For DevOps teams, that is the real value of OpenTofu 1.13: not
fewer question marks at any cost, but better evidence behind the answers a plan 
is willing to give.

## Sources

 * [OpenTofu v1.13.0 release blog](https://opentofu.org/blog/opentofu-1-13-0/)
 * [OpenTofu 1.13.0 release notes on GitHub](https://github.com/opentofu/opentofu/releases/tag/v1.13.0)
