What Changed and Migration
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production; see the section bibliography for the reference material consulted while preparing these pages. |
Infrastructure code outlives the tutorials it was copied from. A configuration written from a book published in 2024 or early 2025 still mostly works, but the tool around it has moved on: the language gained ephemeral values and actions, the S3 backend stopped needing a lock table, the providers shipped new major versions, Terraform Cloud changed its name, a whole alternative interface was archived and the free security scanner was folded into another product. This page collects those changes in one place, with the version or date at which each happened, and says what to do about each.
The baseline is Terraform 1.17 (1.17.0 was released on 2026-10-21) and OpenTofu 1.13 (1.13.0 was released on
2026-09-30). The two books the section draws on were written against Terraform about 1.9 and OpenTofu about 1.8 (Hafner,
2025, with hashicorp/aws at ~> 5.0) and against Terraform 1.4 to 1.8 with hashicorp/google pinned to exactly 5.38.0
(Wang, 2024); both eras therefore end just before the 1.10 release of 2024-11-27. Every date below was checked on the
official release pages, changelogs or registry on 2026-10-24, and what could not be confirmed is worded cautiously. The
page is the last stop of the reading path: each row links to the page of this section that explains the topic in depth,
for example State, Backends and Remote State
and OpenTofu.
Book era to current
The table summarises the points where a configuration, command or habit taught by the books has a different current answer. The detail, including the examples, is on the page named in the last column.
| In the books (2024 to early 2025 era) | Current approach | Where |
|---|---|---|
The S3 backend needs a DynamoDB table for state locking (Hafner) |
|
|
"Terraform Cloud" |
HCP Terraform, renamed on 2024-04-22. The legacy Free plan ended on 2026-03-31. |
|
CDK for Terraform as an alternative interface (Hafner, chapter 11) |
Archived on 2025-12-10; migrate with |
|
|
|
|
|
Deprecated since 1.10: set the |
|
The |
The |
|
tfsec as a separate scanner |
tfsec’s scanning engine is part of Trivy; tfsec stays available but is no longer where development happens. |
|
Secrets passed as plain arguments that end up in state |
Ephemeral resources, variables and outputs (1.10) and write-only arguments (1.11). |
|
|
Current majors with |
|
No |
Always declare |
|
Old action majors such as |
|
|
Test mocks are beta |
Mocks are generally available since 1.7; |
|
|
Deprecated alias of |
|
Static CI secrets in |
OIDC and Workload Identity Federation from CI, HCP Terraform dynamic provider credentials, least-privilege roles. |
|
A Jenkins job that archives |
Never: state holds secrets. Use a remote backend with encryption and locking. |
|
An |
A |
|
A |
Only |
|
A |
The |
|
"No built-in mechanism for module dependencies" (Wang, an error) |
|
|
|
PowerShell: |
|
|
Change the |
|
Retired Google Cloud images, versions and resources: |
Current image families, |
|
|
|
|
|
The |
|
|
|
|
Invented Checkov check IDs and TFLint output; |
Real output from current tool versions; |
Source: Terraform Docs — S3 backend, Terraform v1.11 CHANGELOG, Terraform v1.10 CHANGELOG and Terraform v1.17 CHANGELOG.
The terraform env deprecation and the template_file replacement predate 1.10, so the changelogs above do not mention
them. The terraform env command page states that the command is deprecated and that terraform workspace should be
used instead. The hashicorp/template provider that supplied template_file was archived on 2020-10-08 and is
read-only; the built-in templatefile() and templatestring() functions replace it.
Terraform 1.10 to 1.17
The table lists, per minor release, the release date and the changes that matter when migrating. Dates are the
publication dates of the .0 releases on GitHub; the entries come from the changelog of each minor line. A line of
the changelog is paraphrased, not quoted.
| Version | Released | Changes to know about |
|---|---|---|
1.10 |
2024-11-27 |
Ephemeral resources, ephemeral input variables and outputs, and the |
1.11 |
2025-02-27 |
Write-only attributes. S3 native locking ( |
1.12 |
2025-05-14 |
An OCI Object Storage backend. |
1.13 |
2025-08-20 |
The |
1.14 |
2025-11-19 |
List resources in |
1.15 |
2026-04-29 |
The |
1.16 |
2026-08-26 |
|
1.17 |
2026-10-21 |
Variables and locals in provider requirements. The |
Source: Terraform v1.10 CHANGELOG, v1.11, v1.12, v1.13, v1.14, v1.15, v1.16 and v1.17, and Terraform releases on GitHub.
On 2026-10-24 the latest patch releases listed in the changelogs were 1.17.0 and 1.16.7 (published 2026-10-22). Patch releases of the older lines still receive fixes, as the 1.15.9 and 1.16.x entries show, but the changelogs are the place to look rather than this page. The upgrade guides for each line are the official companion to the changelog; they are referenced at the end of the page.
Deprecations and removals at a glance
| What | Version | Replacement |
|---|---|---|
S3 backend DynamoDB locking arguments |
Deprecated in 1.11 |
|
S3 backend arguments for assuming a role outside |
Removed in 1.10 |
The |
|
Deprecated in 1.10 |
The |
|
Superseded; see the CLI page for the precise status |
|
Experimental |
Lifted in 1.17 |
|
Migrating S3 locking from DynamoDB to use_lockfile
The Bookshelf state lives in an S3 bucket. A book-era backend declares a DynamoDB table; the current one uses a lock file next to the state object. The migration is done in two steps so that both lock sources protect the state during the transition.
terraform {
required_version = ">= 1.11"
backend "s3" {
bucket = "bookshelf-tfstate-example"
key = "prod/network/terraform.tfstate"
region = "eu-west-1"
encrypt = true
use_lockfile = true
# Step 1: keep the old table while every pipeline moves to the new CLI.
# dynamodb_table = "bookshelf-tf-locks"
}
}
Source: Terraform Docs — S3 backend.
Run terraform init -reconfigure after changing the backend block; the state itself does not move. Once every runner uses
a version that supports use_lockfile, remove the dynamodb_table argument and, later, the table. The changelog states
that while both are configured locks are taken from both sources. Native locking needs conditional writes on the bucket;
whether an S3-compatible store such as a local emulator supports them is not documented in the pages consulted, so test
before relying on it. OpenTofu added native S3 locking in its 1.10 line; see
OpenTofu.
Provider major versions
A provider major release is independent of the Terraform version. The table gives the release date of each major according to the Terraform Registry, the most recent version observed on 2026-10-23 and 2026-10-24, and the point the books are behind.
| Provider | Majors and dates | Current (observed) | Book-era pin and what to do |
|---|---|---|---|
|
5.0.0 on 2023-05-25; 6.0.0 on 2025-06-18 |
6.70.0 (2026-10-22) |
Hafner uses |
|
6.0.0 on 2024-08-26; 7.0.0 on 2025-08-26; 8.0.0 on 2026-08-26 |
8.8.x (8.8.1 published 2026-10-23) |
Wang pins exactly 5.38.0. Moving to 8.x crosses three majors, so upgrade one major at a time and clear deprecation warnings first. The 7.0.0 guide adds import-format validation and |
|
4.0.0 on 2024-08-22; 5.0.0 on 2026-07-28 (changelog dated 2026-07-27) |
5.11.0 (2026-10-23) |
The current major is 5.x; 4.x is the previous one, and material that says "AzureRM v4" is outdated. The 5.0 guide, for example, makes |
|
3.0.0 on 2023-01-13; 4.0.0 on 2026-04-03 |
4.6.0 |
A constraint |
|
2.0.0 on 2021-01-21; 3.0.0 on 2025-12-04 |
3.4.0 |
Use the |
|
2.0.0 on 2020-12-19; 3.0.0 on 2025-06-18 |
3.3.0 |
Version 3 is a new major; read its upgrade notes (not summarised here) before changing the constraint. |
Source: Terraform Registry — AWS provider version 6 upgrade guide, Google provider 7.0.0 upgrade guide, Google provider 8.0.0 upgrade guide, AzureRM 5.0 upgrade guide, AzureRM 4.0 upgrade guide, kreuzwerker/docker on the Registry, hashicorp/kubernetes on the Registry and hashicorp/helm on the Registry.
The cloud pages of this section go further: Terraform on AWS, Terraform on Azure, Terraform on Google Cloud and Docker, Kubernetes and Helm Providers.
The safe upgrade procedure is the same for every provider. First upgrade to the last release of the previous major and
run a plan with no unexpected changes and no deprecation warnings; then raise the constraint, run
terraform init -upgrade, and review the plan before applying. The dependency lock file records the chosen version, so
commit the resulting .terraform.lock.hcl change on its own.
terraform {
required_version = ">= 1.17"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
google = {
source = "hashicorp/google"
version = "~> 8.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 5.0"
}
docker = {
source = "kreuzwerker/docker"
version = "~> 4.0"
}
}
}
Terraform Cloud becomes HCP Terraform
Both books say "Terraform Cloud". HashiCorp renamed it HCP Terraform on 2024-04-22. The CLI block that connects to it is
still called cloud, the environment variables keep their TF_CLOUD_ prefix, and the provider is still hashicorp/tfe
(0.82.0 on 2026-10-23). What did change is commercial: the legacy member-based Free plan ended on 2026-03-31, and
organizations moved to the enhanced Free tier, which allows up to 500 managed resources at no charge and is billed per
managed resource beyond that. Hafner’s chapter 8 pricing and limits are therefore outdated. Terraform Enterprise moved to
semantic versions: the monthly scheme ended at v202507-1, and the 2.0.x line is the newest, with 2.0.8
(2026-09-23) as its latest patch release.
CDK for Terraform
The README of the hashicorp/terraform-cdk repository announced that CDKTF would sunset and be archived on
2025-12-10, after which HashiCorp would no longer maintain or develop it. The repository is archived on GitHub today (last
push 2025-12-10). The precise wording is therefore "sunset and archived", not merely "deprecated": the code stays
available read-only under the MPL, with no further fixes or compatibility updates, and the README suggests community
forks. The documented migration path is to generate HCL from the project:
cdktf synth --hcl
terraform init
terraform plan
Source: hashicorp/terraform-cdk on GitHub.
The generated files need review and tidying before they are good HCL. For programmatic access to Terraform, the supported route is the JSON output and the machine-readable UI described in Machine-Readable Output and Integrations.
tfsec to Trivy
The README of aquasecurity/tfsec announces a migration to Trivy: Trivy natively supports Terraform scanning with the
engine tfsec laid the foundations for, and the project encourages tfsec users to move. It also says tfsec "will continue
to remain available for the time being" while engineering attention goes to Trivy; the repository is not archived as of
2026-10-24. In a pipeline, replace the tfsec step by trivy config, and review severity filters and ignore comments,
because the rule identifiers and ignore syntax are not guaranteed to be identical. See
Code Quality and Security Scanning.
Source: aquasecurity/tfsec on GitHub.
Terraform Policy maturity
Terraform Policy is a case where two official sources differ, and both statements are accurate as of 2026-10-24. The
1.17.0 changelog (2026-10-21) says Terraform Policy is now generally available and that the -policies flag for plan,
apply and query no longer requires an experimental build or the -allow-experimental-features flag. The
documentation pages of the policy reference still carried a beta label and the usual warning against using beta features
in production when the section was written. Until the documentation catches up, treat the CLI behaviour as generally
available, the documentation as the more cautious statement, and verify the status on the policy documentation before
making it a gate in production. See Policy as Code.
GitHub Actions majors
The CI examples of this section use actions/checkout@v7 and hashicorp/setup-terraform@v4, and
opentofu/setup-opentofu@v2. These are the majors shown in the READMEs of those repositories on 2026-10-24
(latest releases: checkout v7.0.1 on 2026-07-20, setup-terraform v4.0.1 on 2026-05-12, setup-opentofu v2.0.2 on
2026-06-29). Some tutorials still use setup-terraform@v3 and older checkout majors; those still run, but
the maintained majors are newer. Pin a major (or a full commit hash) and let Dependabot propose bumps.
steps:
- uses: actions/checkout@v7
- uses: hashicorp/setup-terraform@v4
with:
terraform_version: "1.17.0"
- run: terraform fmt -check -recursive
- run: terraform init -input=false
- run: terraform validate
See CI/CD and Automation.
Licensing timeline
| Date | Event |
|---|---|
2023-08-10 |
HashiCorp announces the move from MPL-2.0 to the Business Source License 1.1 for its products, including Terraform. |
2023-09-07 |
Terraform 1.5.7, the last MPL-2.0 release of the 1.5 series, is published. |
2023-09 (day not confirmed) |
The OpenTofu project is accepted by the Linux Foundation; secondary sources give 2023-09-20, which the project’s own pages do not repeat. |
2023-10-04 |
Terraform 1.6.0, the first release under the BSL, is published. |
2024-01-10 |
OpenTofu 1.6.0, the first stable release, under MPL-2.0. |
2025-02-27 |
IBM completes its acquisition of HashiCorp. |
2025-04-23 |
OpenTofu is accepted as a CNCF Sandbox project. |
The BSL announcement date, the CNCF acceptance date and the OpenTofu 1.6.0 date are carried over from the sibling page OpenTofu, which cites the primary sources; the release dates of 1.5.7 and 1.6.0 come from the releases page.
Migration checklist
For a Bookshelf repository written from a book of this era, work through the changes in this order, one commit each:
-
Pin the CLI with
required_versionand move CI to the current action majors. -
Run
terraform init -upgradeon the newest 1.x minor you can adopt, reading the upgrade note of each minor from 1.10. -
Replace
-stateand-state-outby thepathof thelocalbackend, andrefreshandtaintby-refresh-onlyand-replace. -
Switch the S3 backend to
use_lockfile, keep the DynamoDB table for one release cycle, then drop it. -
Upgrade providers one major at a time, starting with the last release of the current major, and review the lock file.
-
Move secrets out of state with ephemeral values and write-only arguments where the provider offers them.
-
Replace
template_filewithtemplatefile(), and tfsec with Trivy. -
Update references to Terraform Cloud and re-check plan limits against the HCP Terraform pricing page.
-
Decide whether OpenTofu is an alternative for your team; the migration notes are on the OpenTofu page.
Reading order after this page: Best Practices and Troubleshooting.