Terraform has become more popular than any other infrastructure as code (IaC) tool. With its popularity, new features have been introduced, some of which are breaking existing functionality, creating difficulties for inexperienced users who don’t use versioning.
In addition to new features coming to Terraform, Terraform providers also release new features regularly. These releases can also introduce breaking changes, and using versioning goes a long way toward protecting against them.
We will cover:
TL;DR
- Check your Terraform version with
terraform -v. - Versioning follows MAJOR.MINOR.PATCH, where patches are safe but minor and major releases can break things, so pin the CLI with
required_versionand providers withrequired_providers(a~> 1.15.0constraint allows patch-only updates). - The latest stable release is Terraform 1.15.x (1.15.8 as of July 2026)
- Upgrade one minor version at a time and read the changelog first.
Why do we need versioning in IaC?
You may wonder why you would need to leverage versioning for IaC too.
Well, infrastructure is the first piece of Lego when it comes to deploying your applications. For every bit of code, versioning should be used, and whenever you use a product, ensure it sticks to a version that doesn’t introduce breaking changes.
Here are four things related to versioning you have to keep in mind when working with Terraform:
- Terraform version: Stick to a specific version for your Terraform code that ensures there are no breaking changes.
- Terraform code versioning: Use a VCS. This can be really helpful for collaboration between teams, and using Git as a single source of truth will considerably reduce the risk of human error.
- Terraform provider version: Stick to a provider version that ensures there are no breaking changes.
- Terraform module versions: Use an exact version of the module.
Now the question becomes, how can you stick to a version that ensures there are no breaking changes? Luckily, when it comes to versioning, the IT world has a widely accepted standard.
Versions are defined as follows: Major.Minor.Patch (e.g. 1.2.7).
In 99.99% of the cases, a Patch change will not affect the current functionality of the product. In some cases, a Minor change will introduce breaking changes, whereas a Major change will most likely bring out breaking changes.
With Terraform, you have the flexibility for both the product and the providers to:
- Lock in a specific version
- Exclude a specific version
- Use a version that is either greater or lower than the version you are specifying
- Allow only the rightmost version to increment
Terraform versions
Let’s now answer some questions that you may have about versioning Terraform.
What is my Terraform version?
To find out which Terraform version you are using, the simplest thing you can do is go to your terminal and run:
Terraform v1.15.7
on darwin_arm64
Your version of Terraform is out of date! The latest version
is 1.15.8. You can update by downloading from https://developer.hashicorp.com/terraform/installThis Terraform command shows your current version and the platform on which it is installed. If you are using an out-of-date version, it will let you know and show you the latest version.
What are the latest versions of Terraform and major Terraform providers?
| Product | Major.minor version | Release date | Latest |
| Terraform | 1.15 | Apr 2026 | 1.15.8 |
| 1.14 | Nov 2025 | 1.14.9 (Apr 20, 2026) | |
| 1.13 | Aug 2025 | 1.13.5 (Nov 5, 2025) | |
| 1.12 | May 2025 | 1.12.2 (Jun 11, 2025) | |
| Terraform provider AWS | 6.54 | Jul 2026 | 6.54.0 (Jul 8, 2026) |
| Terraform provider Azurerm | 4.80 | Jul 2026 | 4.80.0 (Jul 2, 2026) |
| Terraform provider GCP | 7.39 | Jun 2026 | 7.39.0 (Jun 30, 2026) |
* Terraform 1.5.7 was the final release under the open-source MPL 2.0 license. On August 10, 2023, HashiCorp announced that Terraform 1.6 and all later versions would ship under the Business Source License (BUSL 1.1), a source-available license. OpenTofu is an open-source fork created in response to that change, forked from the last MPL 2.0 release and now maintained under the Linux Foundation.
As you can see from the table above, minor versions of the Terraform product have a cycle of a couple of months, whereas minor versions of the Terraform providers come out every couple of weeks/days.
This happens because major cloud providers are evolving rapidly and adding new resources or features to existing ones faster.
Terraform version constraints
As mentioned before, you can introduce version constraints in multiple ways.
1. Equal constraint
Terraform
terraform {
required_version = "=1.5"
}Terraform Provider AWS
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "=5.10.0"
}
}
}In this example, we are pinning the Terraform version to 1.5 and the AWS provider version to 5.10.0.
2. Not equal constraint
Terraform
terraform {
required_version = "!=1.5"
}Terraform Provider AWS
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "!=5.10.0"
}
}
}The Terraform version can be anything that is different from 1.5, and the Terraform AWS provider can be anything different from 5.10.0.
In this case, Terraform will try to get the latest version, but if the latest version is the one specified in the constraint, it will get the second latest version.
3. Greater/less or equal to constraint
Terraform
terraform {
required_version = ">=1.5"
}Terraform Provider AWS
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">=5.10.0"
}
}
}In this case, we are trying to get versions that are greater than or equal to the constraint specified for both Terraform and the AWS provider. This works in the same way for the lower constraint.
4. Allow only the rightmost version to increment
Terraform
terraform {
required_version = "~>1.5.0"
}Terraform Provider AWS
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~>5.10.0"
}
}
}Allowing only the most upright version to increment for patches is actually one of the best practices for managing your Terraform and Terraform provider versions.
In this case, for Terraform, only the Patch (0) will be incremented if a new patch version comes up, ensuring there is a minimal chance of a breaking change.
A similar thing happens with the AWS provider: the Patch (0) is incremented only when a new patch version is released.
5. Breaking changes in minor versions
Historically, Terraform saw the biggest changes from version 0.11 to 0.12. Of course, breaking changes appeared in other versions, but this one had a lot to do with the language’s syntax.
0.11 syntax
resource "aws_instance" "example" {
ami = "${var.ami}"
instance_type = "${var.instance_type}"
tags {
Name = "${var.instance_name}"
}
}
variable "ami" {
default = "ami-0c94855ba95c574c8"
}
variable "instance_type" {
default = "t2.micro"
}
variable "instance_name" {
default = "terraform-example"
}0.12 syntax
resource "aws_instance" "example" {
ami = var.ami
instance_type = var.instance_type
tags {
Name = var.instance_name
}
}
variable "ami" {
default = "ami-0c94855ba95c574c8"
}
variable "instance_type" {
default = "t2.micro"
}
variable "instance_name" {
default = "terraform-example"
}The syntax for 0.11 became obsolete with the release of 0.12, even though Terraform maintained a degree of backward compatibility and many 0.11 style expressions still worked.
In this case, if you didn’t pin your version by allowing only the Patch version to increment, your code would’ve been in big trouble.
Usually, when a minor version is being released, an upgrade guide also becomes available, as you can see in the image below:

Upgrade guides indicate the best way to upgrade your current configuration to support the next version of Terraform, but sometimes they don’t include all the necessary information you need, and you may need to figure things out yourself.
Some guides for versions prior to 1.x, also come with an upgrade script that takes care of some of the breaking changes for the user. These won’t solve your problems completely, but they are still a great starting point.
Here’s an interesting fact: In 0.12, Terraform dynamic blocks and the for_each loops were introduced, becoming two of Terraform’s best features.
How to upgrade your code / Terraform version
The most important thing to understand is what has changed in a new Terraform version. For that, you should head to Terraform’s GitHub repository, and go to the Releases page.
On the Releases page, you can find information about the latest available versions. Pre-releases are marked with the pre-release tags and usually have an alpha in the tag name. I believe you should avoid using pre-releases as they are unstable, but it is important to note what features are coming up.

For example, this is how I first spotted that the terraform test command was graduating from experimental. It has since shipped as a stable, documented feature in Terraform 1.6.
Now, let’s look at the changelog for 1.5.0.
In this version, we can see there are no breaking changes, and that makes our lives easier. However, if you want to adopt the latest features, like the check block and the newly configuration-driven import, you will need to upgrade.
Upgrading your local Terraform version can be done by:
- Downloading the version you are interested in for your operating system and replacing the one you already have
- Using tfswitch – a tool you can install locally, that can switch to any Terraform version you’d like
- Using tfenv – an alternative to tfswitch
After you have installed the version you want, you should check if this version has added any breaking changes to the configuration.
This also depends on the version you currently have, so if we take a look at Terraform 1.5.0 again, we see that it didn’t add any breaking changes from 1.4.0, but if you come from 0.12, for example, you will need to go through the changelog of each minor release to understand what has happened.
Usually, you will need to migrate to a new minor version step by step until you reach the version you desire, but if you reach 1.0.x, you can potentially jump to the latest v1.x minor version because of the Compatibility Promises for 1.x.
Sometimes, you may run a terraform plan/apply and see deprecation messages related to your code. It is best to fix these as soon as possible because otherwise when you are upgrading to a newer version in a couple of months, you may notice these are becoming obsolete.
Which Terraform version to use?
In an ideal world, we would all use the latest stable version of Terraform, but in big organizations, this is clearly impossible due to time constraints and technical debt.
Whenever you are in charge of a Terraform project, it is important to have an upgrade strategy for all the code that is written. This can seem time-consuming, but if one of your engineers is in charge of overlooking this bi-weekly for less than 30 minutes, it will be a great time saver in the end.
When the big syntax change happened from 0.11 to 0.12, I had already implemented over 25 Terraform modules for the company I was working with at that time. As I am really focused on reusability, all these modules used count, giving you the flexibility to create as many resources of a given type as you wanted and to create relationships between them easily.
As 0.12 approached, I knew about the syntax changes and had tried them in the pre-release, so I knew what the upgrade process would look like and how long it would take. Later, in 0.12.6, when for_each was added, I replaced all occurrences of count with for_each, and I had to go through the process of ensuring everything was working properly again.
I always aim to use the latest stable version of Terraform (Patch included), but I am happy to use at least the latest stable minor version. This is a challenging process, but it’s better to go one step at a time rather than undergo a big upgrade from a very old version to the latest one.
Terraform provider versions
Products are evolving at different paces, with different APIs and features. That’s why you need a provider for interacting with a tool via Terraform.
Identifying providers in a Terraform configuration
Whenever you run terraform init, you will see all the providers in your configuration. The output will be different depending on whether there is a .terraform directory and a .terraform.lock.hcl file created already.
For a first run, for example, the output for running terraform init on an AWS configuration would be similar to:
terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "5.10.0"...
- Installing hashicorp/aws v5.10.0...
- Installed hashicorp/aws v5.10.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider selections it made above. Include this file in your version control repository so that Terraform can guarantee to make the same selections by default when you run "terraform init" in the future.If you are running this a second time, the output will be similar to:
terraform init
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v5.10.0You can also run the terraform providers command to get the versions you are using for your providers:
terraform providers
Providers required by configuration:
.
└── provider[registry.terraform.io/hashicorp/aws] 5.10.0How to upgrade to a new provider version
To upgrade to a new provider version, the same process applies as for upgrading your Terraform version. Let’s suppose we are using the AWS provider and would like to upgrade from the second major version to the latest major version from the second to the latest one. To do the upgrade, we would:
- First, go to the Changelog of the latest Major version, which is 5.x.
- Identify whether you are using any resources, data sources, or provider configurations affected by the change, and make the necessary code changes.
- Increment the required provider version in your Terraform configuration and run
terraform init -upgrade.
Best practices for Terraform versioning
The most important best practices when it comes to your Terraform and Terraform providers’ versions are:
- Pin versions to increment only the patch, minimizing the chance of breaking changes.
- Whenever you see deprecations, take time to solve them, as what is deprecated today may become obsolete tomorrow and break your code.
- Always version your Terraform configurations and Terraform modules.
- Have an upgrade strategy for both Terraform and your Terraform providers
- Always follow Terraform’s GitHub repository and the repository for the provider you are using to be prepared for the next updates (weekly or bi-weekly basis should be just fine).
Deploying Terraform resources with Spacelift
Terraform provisions infrastructure well on its own, but a secure GitOps workflow needs a platform that can run your Terraform for you. Spacelift takes managing Terraform to the next level by giving you access to a powerful CI/CD workflow and unlocking features such as:
- Policies (based on Open Policy Agent) – You can control how many approvals you need for runs, what kind of resources you can create, and what kind of parameters these resources can have, and you can also control the behavior when a pull request is open or merged.
- Multi-IaC workflows – Combine Terraform with Kubernetes, Ansible, and other IaC tools such as OpenTofu, Pulumi, and CloudFormation, create dependencies among them, and share outputs.
- Build self-service infrastructure – You can use Templates and Blueprints to build self-service infrastructure; simply complete a form to provision infrastructure based on Terraform and other supported tools.
- AI-powered provisioning and diagnostics – Spacelift Intelligence adds an AI-powered layer for natural language provisioning, diagnostics, and operational insight across your infrastructure workflows.
- Integrations with any third-party tools – You can integrate with your favorite third-party tools and even build policies for them. For example, see how to integrate security tools in your workflows using Custom Inputs.
Spacelift enables you to create private workers inside your infrastructure, which helps you execute Spacelift-related workflows on your end. Read the documentation for more information on configuring private workers.
You can check it for free by creating a trial account or booking a demo with one of our engineers.
Key points
In this post, we’ve dived deep into Terraform versions and Terraform provider versions and gone through the process of upgrading them while learning some best practices to keep your infrastructure safe.
If you need a specialized platform that manages your IaC workflow and helps with your Terraform versions, Spacelift is your answer. Start a free trial or book a demo with our engineering team to discuss your options in more detail.
Orchestrate Terraform deployments with Spacelift
Orchestrate your Terraform workflows and build governed pipelines using policy as code, programmatic configuration, context sharing, drift detection, resource visualization, and many more.
Frequently asked questions
What do Terraform version numbers mean (e.g., 1.14.3)?
Terraform uses semantic versioning: MAJOR.MINOR.PATCH. In general, minor and patch releases are intended to be backward compatible with earlier configuration (within the same major line).
How to pin Terraform version in required_version?
Set required_version inside the terraform block using a version constraint. Use an exact pin with = 1.6.6, or a controlled range like ~> 1.6.0 (allows 1.6.x) or >= 1.6.0, < 1.7.0.
What’s the difference between Terraform CLI versions and provider versions?
Terraform CLI version controls the language evaluation, planning engine, state handling, etc. Provider versions control how resources are implemented for a given API (AWS, Kubernetes, etc.).

