CloudInfrastructure as code

Terraform 1.17 explained: provider variables, minimal refresh and Policy GA

Terraform 1.17.0 is out. Variables work in required_providers, -minimal-refresh speeds up big plans at the cost of some drift detection, and Terraform Policy runs in the normal CLI. What changed from 1.16, and how we'd upgrade.

Cohash Cloud Engineering Practice October 2026 13 min read 4 chapters 3-question check
part 3 of 3 · Platform releases, explained from scratch
TERRAFORM 1.16 Fixed providerstrings Refresh everything Policy flagexperimental TERRAFORM 1.17 Vars in providersources -minimal-refreshoption Policy GA in the CLI

the idea1.17 adds provider variables, a lighter plan and GA policy checks.

after reading, you can
  • Tell your team which Terraform 1.17 changes affect them and which don't
  • Spot when -minimal-refresh is safe and when it'll hide drift you need to see
  • Set up an upgrade to 1.17 that checks pins, parsers and certificate paths first

Terraform 1.17.0 came out on October 21, 2026. Read on if you run large states (there's a new -minimal-refresh option with a catch), keep providers in more than one private registry (required_providers now takes constant variables and locals), or write policy (Terraform Policy no longer needs an experimental build). Otherwise it's a quiet 1.x minor eight weeks after 1.16.0.

  • You describe infrastructure in HCL, HashiCorp's configuration language.
  • Providers are plugins that call each API: AWS, Azure, Snowflake, Okta.
  • A state file records what Terraform already manages.
  • terraform plan previews a change, and terraform apply makes it.
  • IBM owns HashiCorp (Feb 2025); Terraform is under the BSL (Aug 2023).
Oct 21, 2026Terraform 1.17.0 published on GitHub
3items under New Features in the 1.17.0 changelog
1.16.71.16 patch shipped the next day, October 22, 2026
Go 1.26.10toolchain for 1.17.0 and 1.16.7, which drops trust in compromised eMudhra intermediates
chapter 01

What changed in 1.17

Not much to read this time: three new features, three enhancements, seven bug fixes and two notes. Tags are HashiCorp's, except the notes, which we marked changed.

Terraform 1.17.0 at a glance

newVariables and locals in provider requirements

You can now take the source and version in required_providers from constant input variables and locals. Same rules as 1.15's dynamic module sources: nothing may depend on plan results.

newplan -minimal-refresh

Refreshes only the resource instances Terraform plans to change, so plans on big states make fewer API calls. Drift on unchanged resources goes unseen.

newTerraform Policy is GA in the CLI

The -policies flag for plan, apply and query no longer needs an experimental build or -allow-experimental-features. Query policies check resources that list blocks discover.

enhancedinit logs show provider versions

Log lines from terraform init now name the provider versions. Handy when you're working out why an install failed.

enhancedMock providers cover ephemeral resources

terraform test's mock_provider can now fake ephemeral resources, so a test of a module that uses them can run on mocks.

fixedEphemeral renewal diagnostics surface

Terraform used to drop warnings and errors from ephemeral resource renewals. It shows them now, so a few new warnings may turn up.

fixedlog and pow stop at infinity

No more panics from log and pow when the result isn't a number. They also error out now on plus or minus infinity, which nothing downstream could use anyway.

changedterraform version JSON gets format_version

There's a format_version field in terraform version -json now. If your tooling ignores unknown fields you're fine, but watch the field in later releases.

Provider requirements can now use variables, within limits. This builds on 1.15 (April 29, 2026), where module source and version started reading variables marked const = true and locals built from them. Now required_providers can too. Don't be thrown by HashiCorp's reference page for the terraform block, which still says it won't take input variables. The pull request's example uses an organization variable inside a private registry address and keeps the version in a local. Set the values with -var, a var file or environment variables.

This is useful if one codebase runs against more than one private registry or organization. Until now, teams in that position kept near-identical copies of the terraform block, or rewrote it with scripts before init. One limit doesn't move. The value has to be known before planning starts, so it can't come from a resource or a data source. Terraform 1.15 rejects that case at init for module sources with an "Invalid module source" error, and provider sources follow the same constraints.

A faster plan for big states, if you accept the trade-off. Normally a plan refreshes every resource it manages before doing anything else, which costs at least one read call each. On a state with thousands of resources, that's the slow part, and it's also when providers start rate limiting. Issue 35290 asked for a fix back in 2024, from someone who found -refresh=false too risky. -minimal-refresh has Terraform compare configuration with the prior state first. Instances with no planned change skip the refreshdefinitionBefore planning, Terraform asks each API what really exists and updates state to match. That's the refresh, and on big states it's the slow part., and the ones with changes are refreshed and planned again. Each one decides for itself, so refreshing one resource doesn't pull in the ones that depend on it.

The documentation is frank about the cost. Like -refresh=false, it ignores changes made outside Terraform to anything you didn't touch, so the plan can be incomplete or wrong. You can't combine it with refresh-only mode or with -refresh=false. HashiCorp also says to avoid it when you upgrade provider versions, so Terraform can write schema changes into state. We'd use it for fast feedback on pull requests and keep a full-refresh plan in front of every production apply.

Terraform Policy is out of experimental status in the CLI. For anyone who hasn't tried it, it's HashiCorp's HCL-based policy as code: .policy.hcl files with provider, resource and module blocks. HCP Terraform can evaluate them at setup time, before providers or modules download, at plan time and after apply, when IDs and ARNs exist. Enforcement is Advisory, Mandatory_overridable or Mandatory. Sentinel and Open Policy Agent haven't gone away.

From 1.17, -policies works on plan, apply and query in a normal build. Query policies check what your list blocks find and report as text or JSON. Before you call it production-ready, though, look at the docs too. HashiCorp's Terraform PolicydefinitionHashiCorp's HCL-based policy as code, kept in .policy.hcl files. docs (v0.5.x) still said "this functionality is in beta" when we checked on October 22, 2026. Easy to miss: the pull request the GA entry links to changes how policies see a replacement. It now arrives as a separate create and delete, each with its own attribute values. It used to be one update.

Smaller changes that can still show up in your pipeline. Two fixes could change output you're used to. Diagnostics from renewing ephemeral resources now appear, and HashiCorp doesn't expect that to break anything. log and pow now fail instead of returning infinity. If a wrapper parses terraform version -json, check that it tolerates the new format_version field. And if anything in your build trusts certificates through the compromised eMudhra intermediates, the Go 1.26.10 change in 1.17.0 and 1.16.7 will make those connections fail.

chapter 02

Version against version

A quick sense of pace: a minor release every few months, a patch to the current one most weeks. Here's 1.17 next to the two before it, headline items only. The changelogs have everything else.

tableTerraform 1.15, 1.16 and 1.17 compared, from HashiCorp's GitHub changelogs
Item1.151.161.17
ReleasedApril 29, 2026August 26, 2026October 21, 2026
Latest patch (Oct 22, 2026)1.15.9 (August 19, 2026)1.16.7 (October 22, 2026)1.17.0
Dynamic sources from const valuesModule source and version from const variables and localsNo change in the changelogProvider source and version from const variables and locals
ImportNo headline changeimport blocks work inside modulesNo headline change
Refresh and planningNo headline changeNo headline change-minimal-refresh option
PolicyNo mention in the changelogHCP Terraform policy summaries in the CLI; plugin credentials from the backendTerraform Policy GA for -policies on plan, apply and query
Lifecycle and actionsNo headline changelifecycle destroy = false; on_failure modes halt, taint, continueNo headline change
Platforms, output and syntaxWindows ARM64 builds; deprecated attribute on variables and outputsLinux s390x builds; graph -format=mermaid; state show -jsonformat_version in version JSON
Upgrade notesS3 backend FIPS and dual-stack env vars accept only true or falseProvisioners now apply bastion_host_key; check itNone listed; upgrade guide cites the 1.x promises

How long will 1.16 be supported? Nobody has published a date we can point you to. What we can see is that 1.16 is still getting patches: 1.16.7 arrived the day after 1.17.0. The support-period article now redirects to IBM's support portal, which didn't load for us without a sign-in, and the public 1.x compatibility promise only says the series gets at least 18 months of maintenance after 1.0. If you need a date for an audit or a contract, ask HashiCorp support.

Terraform releases and advisories, November 2025 to October 2026

  1. Nov 19, 2025
    Terraform 1.14.0

    List resources, the terraform query command and the actions block arrive.

  2. Apr 29, 2026
    Terraform 1.15.0

    Const variables in module sources, Windows ARM64 builds, the convert function.

  3. Jul 6, 2026
    HCSEC-2026-17 (Terraform Enterprise)

    Module publishers could pull arbitrary files through VCS ingestion. Patch to 2.0.4 or 1.2.4.

  4. Jul 28, 2026
    HCSEC-2026-23 (terraform-mcp-server)

    Three CVEs in the HTTP transport. Fixed in 1.1.0.

  5. Aug 26, 2026
    Terraform 1.16.0

    import in modules, terraform_data store block, destroy = false.

  6. Sep 9, 2026
    1.17.0-beta1
  7. Oct 7, 2026
    1.17.0-rc1

    rc2 followed on October 14.

  8. Oct 21, 2026
    Terraform 1.17.0

    Provider requirement variables, -minimal-refresh, Terraform Policy GA.

  9. Oct 22, 2026
    Terraform 1.16.7

    Go 1.26.10 for 1.16 users who aren't moving yet.

And two advisories from this summer. Neither is in the Terraform CLI. If you run self-managed Terraform Enterprise, read HCSEC-2026-17: a user who can publish a registry module from a VCS repository could pull files from outside it into the module and download them. It hits v202506-1, v202507-1 and 1.0.0 through 2.0.3, with fixes in 2.0.4 and 1.2.4. If you run terraform-mcp-server, HashiCorp's MCP server for AI tools, read HCSEC-2026-23. Versions 0.2.1 through 1.0.0 had three HTTP transport flaws, one of which could send the server's bearer token to an attacker's endpoint. 1.1.0 fixes them; stdio-only setups were safe.

chapter 03

Architecture and the upgrade

Nothing about Terraform's overall shape changes in 1.17: configuration, the CLI or a remote runner, providers, state, and the APIs at the end. A few decisions move. Init can work out a provider's address from variables, a plan can skip refreshing what you didn't touch, and you don't need an experimental build to run policy from the Terraform CLI. We've used HashiCorp's own component names in the diagrams and simplified the rest.

before

Before: a Terraform 1.16 run

Under 1.16 you hard-code the provider address, every plan refreshes every managed resource, and -policies only works in an experimental build.

Before: a Terraform 1.16 run Under 1.16 you hard-code the provider address, every plan refreshes every managed resource, and -policies only works in an experimental build. 01 · CONFIGURATION 02 · TERRAFORM CLI 03 · STATE AND APIS provider address module sources read prior state refresh all opt-in, experimental Root module and modules module sources may use constvars required_providers fixed source and versionstrings terraform init installs providers andmodules terraform plan refreshes everymanaged resource -policies flag experimental builds only State file remote backend, locked Provider APIs one read per resource onrefresh
Read the diagram as text
  1. required_providers → terraform init: provider address
  2. Root module and modules → terraform init: module sources
  3. terraform init → terraform plan
  4. terraform plan → State file: read prior state
  5. terraform plan → Provider APIs: refresh all
  6. -policies flag → terraform plan: opt-in, experimental
after

After: a Terraform 1.17 run

In 1.17 provider addresses can come from const variables and locals, -minimal-refresh limits refresh to changed resources, and -policies works in a normal build.

After: a Terraform 1.17 run In 1.17 provider addresses can come from const variables and locals, -minimal-refresh limits refresh to changed resources, and -policies works in a normal build. 01 · CONFIGURATION 02 · TERRAFORM CLI 03 · STATE AND APIS known before plan provider address -policies (GA) query policies read prior state refresh changed only Const variables andlocals -var, var files, env vars required_providers source and version from vars .policy.hcl files Terraform Policy, HCL terraform init resolves provider address terraform plan full, or-minimal-refresh terraform query list blocks, query policies State file remote backend, locked Provider APIs fewer reads with minimalrefresh
Read the diagram as text
  1. Const variables and locals → required_providers: known before plan
  2. required_providers → terraform init: provider address
  3. terraform init → terraform plan
  4. .policy.hcl files → terraform plan: -policies (GA)
  5. .policy.hcl files → terraform query: query policies
  6. terraform plan → State file: read prior state
  7. terraform plan → Provider APIs: refresh changed only
side by sideDay to day on Terraform 1.16 against 1.17
Terraform 1.16
  • Provider source and version are hard-coded strings in each terraform block
  • Every plan refreshes every managed resource, or you turn refresh off entirely
  • Running -policies locally means an experimental build and an extra flag
  • A replaced resource reaches policy as a single update
  • terraform version -json has no format_version field
Terraform 1.17
  • Provider source and version can come from const variables and locals
  • -minimal-refresh refreshes only the instances you're changing
  • -policies works on plan, apply and query in a normal build
  • A replaced resource is evaluated as a separate create and delete
  • terraform version -json includes format_version

Don't expect much from the upgrade guide. For 1.17 it says the release honors the v1.0 compatibility promises and points you at the changelog. That's normal inside 1.x. If something breaks, look at providers first, then at scripts that parse CLI output, then at the edge cases in the bug fixes. This is the order we'd go in.

Upgrading from 1.16 (or earlier) to 1.17

  1. 01
    Inventory versions and pins

    List the Terraform version every pipeline, runner and laptop uses, and every required_version constraint. A constraint like ~> 1.16.0 blocks 1.17 until you change it. If you're on 1.15 or earlier, read the upgrade notes in the 1.16 and 1.15 changelogs too: bastion_host_key for provisioners, and the S3 backend's FIPS and dual-stack variables.

  2. 02
    Check what parses Terraform's output

    Track down anything that reads terraform version -json and make sure it ignores unknown fields or reads format_version. HashiCorp's advice is to use current hashicorp/terraform-json and terraform-exec.

  3. 03
    Check certificate paths

    Go 1.26.10, used for 1.17.0 and 1.16.7, no longer trusts certificates from the compromised eMudhra intermediates. If a private registry, proxy or backend chains through one, it'll break, so check before rollout.

  4. 04
    Run plans side by side in a lower environment

    Run plans with 1.16 and 1.17 against the same state with the same provider versions, with full refresh. Expect identical plans. Watch for new warnings from ephemeral resource renewals and errors from log or pow.

  5. 05
    Upgrade providers separately

    Don't change Terraform and provider versions in the same step. During provider upgrades, plan without -minimal-refresh or -refresh=false so schema changes reach state.

  6. 06
    Adopt the new features on purpose

    Move duplicated terraform blocks to const variables where it helps. Try -minimal-refresh on pull-request plans. Pilot Terraform Policy beside your Sentinel or OPA rules before you rely on it.

  7. 07
    Cut over and record it

    Raise required_version, rebuild runner images and set the new version on your HCP Terraform or Terraform Enterprise workspaces. Production applies still get a full-refresh plan first.

chapter 04

Who gains from 1.17

Most of what's in 1.17 helps platform teams that run Terraform for other teams. If you write a few modules for one account, you can take this release at your own pace.

  • Platform teams with one codebase and several private registries or organizations: set the provider source per environment and stop copying terraform blocks or patching them with scripts.
  • Teams whose large states run into provider rate limits get a supported halfway house between a full refresh and -refresh=false when they just want a quick plan.
  • If you write guardrails, you can run HCL policies from the Terraform CLI in CI now. Policies see a replacement as a create and a delete.
  • Anyone wrapping the CLI in scripts gets versioned JSON from terraform version, which makes it easier to notice when the format changes later.
  • Teams staying on 1.16 for now still get the Go 1.26.10 certificate change through 1.16.7.

If you run self-managed Terraform Enterprise or a shared terraform-mcp-server, check the two bulletins above first. They matter more than anything in the 1.17 changelog.

Cohash writes and maintains Terraform for clients: module design, state clean-up, version upgrades. Our Terraform platform page has the detail. If you'd rather staff it yourself, hire Terraform engineers through us, or ask for a free assessment of your code, state and pipelines first. The DevSecOps practice handles pipelines and policy.

key takeaways

What to take from this

  1. 01

    1.17.0 shipped October 21, 2026. HashiCorp lists no special upgrade steps.

  2. 02

    Const variables and locals now work in required_providers when they're known before planning.

  3. 03

    -minimal-refresh saves API calls but hides drift on untouched resources. Put a full plan in front of production applies.

  4. 04

    Terraform Policy is GA for -policies in the CLI, even though the policy docs still said beta on October 22.

  5. 05

    Before rollout, check whatever parses terraform version -json and any certificate chain through the eMudhra intermediates.

platforms in this noteTerraform →
fact-checked October 2026 against vendor and official documentation · where to go next
  1. How Cohash delivers Terraform: scope, roles and architecture
  2. Hire vetted Terraform engineers
  3. DevSecOps practice
  4. Book a 30-minute working session with a senior engineer
01Is upgrading from Terraform 1.16 to 1.17 a breaking change?

HashiCorp doesn't treat it as one. It's a 1.x minor release that keeps the v1.0 compatibility promises, and the upgrade guide lists no special steps. The things we'd still check are tools that parse terraform version -json, new warnings from ephemeral renewals, log and pow erroring on infinity, and certificate chains affected by Go 1.26.10.

02What does terraform plan -minimal-refresh do?

It refreshes only what Terraform plans to change, so a large state makes fewer API calls. The catch: anything changed outside Terraform on the other resources goes unseen. It won't combine with refresh-only mode or -refresh=false, and HashiCorp says to leave it off during provider upgrades.

03Can I use variables in required_providers now?

In 1.17 you can, as long as the values are known before planning. Use input variables declared with const = true, or locals built from them, for source and version. Resources and data sources won't work there.

04Is Terraform Policy generally available?

The 1.17.0 changelog says so for the CLI's -policies flag. HashiCorp's policy docs still showed a beta note on October 22, 2026. Ask HashiCorp before you gate production on it.

05Do the two 2026 bulletins covered here affect the Terraform CLI?

No, neither does. HCSEC-2026-17 is in self-managed Terraform Enterprise (fixed in 2.0.4 and 1.2.4) and HCSEC-2026-23 is in terraform-mcp-server 0.2.1 through 1.0.0 (fixed in 1.1.0). The CLI had its own fixes, mind you: 1.15.9 updated go-slug for CVE-2026-14978, and 1.17.0 and 1.16.7 ship Go 1.26.10 for CVE-2026-111943.

keep reading

More field notes

Other notes from the same practices, newest first.

next step

Tell us what you're running. We'll tell you what we'd do first.

A 30-minute working session with a senior engineer. No slides.

useful to bring
  • The platform and the version you're on
  • Where you need to get to, and by when
  • What's custom: rules, plugins, integrations
  • Any audit finding or deadline driving it