Stable Release in branch 1.15
1.15.9
Released 19 Aug 2026
(1 month ago)
SoftwareTerraform
Version1.15
Initial release1.15.0
29 Apr 2026
(5 months ago)
Latest release1.15.9
19 Aug 2026
(1 month ago)
End of security fixesTBD
Release noteshttps://github.com/hashicorp/terraform/blob/v1.15/CHANGELOG.md
Source codehttps://github.com/hashicorp/terraform/tree/v1.15
Documentationhttps://developer.hashicorp.com/terraform/docs
Downloadhttps://releases.hashicorp.com/terraform/
Terraform 1.15 ReleasesView full list

What Is New in Terraform 1.15?

Terraform 1.15 ships a meaningful set of additions: native deprecation markers on variables and outputs, a new convert() function for explicit type coercion, support for variables and locals inside module source and version attributes, and Windows ARM64 builds. Backend validation now runs at init time, and S3 backends gain aws login authentication. Below is a summary by category.

Category Highlights Count
New Features Windows ARM64 builds, deprecated attribute on variables/outputs, convert() function, variables in module source/version, S3 aws login auth, backend validation in validate 6
Enhancements Typed output blocks, PowerShell re-enabled for SSH provisioners, millisecond timestamps in init, skip dev-override deps, functions in test mock blocks, richer deprecation messages, sensitive path logging 8
Bug Fixes JUnit XML diagnostics, refresh-only plan exit codes, ephemeral resource crash in show -json, init -json backend messages, state show exit code, cross-workspace apply guard, HTTP backend lock info, output diff detection 13
Deprecated / Upgrade Notes S3 backend: AWS_USE_FIPS_ENDPOINT and AWS_USE_DUALSTACK_ENDPOINT now only accept true/false 1
Experimental (alpha only) Deferred actions (-allow-deferral), terraform test cleanup, backend blocks in test run blocks, skip_cleanup 4

Which New Features Ship in Terraform 1.15?

Windows ARM64 Support

Terraform now publishes official binaries for Windows ARM64, so developers running Snapdragon-based Windows machines get native performance without emulation layers. This is a build artifact change -- no HCL changes are needed.

Deprecation Markers on Variables and Outputs

You can attach a deprecated attribute to any variable or output block. When a caller passes a value to a deprecated variable, or when downstream config references a deprecated output, Terraform emits a warning. In practice, this is the cleanest way to signal API changes in shared modules without breaking callers immediately.

variable "old_param" {
  type       = string
  deprecated = "Use new_param instead. This variable will be removed in a future release."
}

output "legacy_endpoint" {
  value      = aws_lb.main.dns_name
  deprecated = "Reference module.lb.endpoint going forward."
}

The convert() Function

The new built-in convert(value, type) performs an explicit, inline type conversion. Before this, coercing a value to a specific type required indirect workarounds like tostring(), tonumber(), etc. Now you can express the target type as a full type expression -- including complex types -- directly in the call.

# Convert a string to a number explicitly
locals {
  port = convert(var.raw_port, number)
}

# Convert to a typed object
locals {
  record = convert(var.input, object({ name = string, count = number }))
}

Variables and Locals in Module source and version

Module source and version attributes now accept input variables and locals. This was a long-requested capability for teams that dynamically compose registries or pin versions based on workspace-level variables. Most commands that consume variable values have been updated to support this pattern.

variable "module_version" {
  type    = string
  default = "2.1.0"
}

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = var.module_version
}

Backend Block Validation in terraform validate

The validate command now inspects your backend block, checking that the backend type exists, all required attributes are present, and the backend's own validation logic passes. This surfaces misconfigured backends before init -- useful in CI pipelines where you want early failure on config errors.

S3 Backend: aws login Authentication

The S3 backend now supports authentication via aws login, the credential flow introduced in recent AWS CLI versions. This complements existing auth methods (env vars, profiles, instance roles) and is the right choice for short-lived credential workflows.

What Got Better -- Enhancements in 1.15

Typed output Blocks

output blocks now accept an explicit type constraint, mirroring what variable blocks have always supported. This lets module authors enforce the shape of their outputs and catch type mismatches at plan time rather than at consumption time.

output "instance_ids" {
  value = aws_instance.web[*].id
  type  = list(string)
}

PowerShell Re-enabled for SSH Provisioners

The file and remote-exec SSH-based provisioners now support PowerShell again. This restores a capability that had been disabled, making Windows remote provisioning via SSH first-class again for teams that still use provisioners.

Millisecond Timestamps in init Logs

terraform init log timestamps now include millisecond precision. Minor QoL improvement, but meaningful when diagnosing slow provider installs in CI where sub-second timing matters.

Skip Dev-Override Dependencies During init

When using developer overrides (dev_overrides in CLI config), terraform init now skips installing providers declared in the override file. This means you no longer need to remove dev overrides to run init successfully -- it installs only the providers that are not overridden.

Functions in Test Mock Blocks

Terraform Test now allows function calls inside mock_provider blocks. This makes mock data generation much more expressive -- you can call uuid(), timestamp(), or string functions directly in mock definitions without external workarounds.

Richer Deprecation Warnings from Providers

When a provider marks a resource attribute or block as deprecated, that deprecation message is now surfaced directly in the Terraform warning output. Previously, users had to dig into provider docs to understand what was being deprecated. Now the context travels with the warning.

Sensitive Attribute Paths in JSON Logs

Structured JSON logs (list_start events) now include the specific attribute paths that are marked sensitive. This is useful for log parsers and auditing pipelines that need to know exactly which attributes were redacted.

Input Variable Validation for Stacks

Stacks now run input variable validation rules, consistent with how standard Terraform configs handle variable constraints. This closes a gap where stack-level inputs could bypass validation logic that module authors had defined.

What Bugs Were Fixed in Terraform 1.15?

The 1.15 bug fix list is notably broad. Here are the ones most likely to affect day-to-day work:

  • Refresh-only plan exit codes: A refresh-only plan could return a non-zero exit code even when there were no changes to report. This caused false failures in CI pipelines checking exit codes.
  • Cross-workspace apply guard: Terraform now raises an explicit error when you attempt to apply a plan file against a workspace that differs from the one the plan was generated for. Previously this could silently proceed.
  • terraform show -json crash: Fixed a crash that occurred when a plan contained ephemeral resources with precondition or postcondition blocks.
  • terraform init -json output format: Backend configuration messages now emit proper JSON when -json is passed. Previously, some messages fell through as plain text, breaking JSON log consumers.
  • state show exit code: The command now exits with code 1 when it cannot render the named resource state. Before this fix it could exit 0 silently on failure.
  • replace_triggered_by invalid reference: The lifecycle meta-argument now reports a proper error when given an attribute reference that does not exist in the target resource, instead of silently ignoring it.
  • Output diff detection: Fixed a bug where Terraform could fail to detect differences between two states that had differing output values. This affected backend migration scenarios.
  • HTTP backend lock info: The HTTP backend now returns the conflicting lock info when a lock cannot be acquired, rather than returning the lock that failed. This gives operators the correct information to resolve lock contention.
  • JUnit XML test diagnostics: File-level error diagnostics are now included in JUnit XML output for skipped test elements, so CI systems can detect validation failures that were previously invisible in test reports.
  • nil pointer crash in init: Fixed a nil pointer dereference that could occur during terraform init when the destination backend returned an error.
  • terraform fmt for .tfquery.hcl: The formatter now handles .tfquery.hcl files, which were previously not recognized.
  • Cloud/registry network resilience: Terraform Cloud and registry discovery requests are more resilient to transient network errors, reducing spurious init failures.
  • validate JSON output: Fixed cases where validate did not return JSON for certain early diagnostics when -json was passed.

What Should You Watch Out For When Upgrading to 1.15?

S3 Backend: FIPS and Dual-Stack Environment Variables

The AWS_USE_FIPS_ENDPOINT and AWS_USE_DUALSTACK_ENDPOINT environment variables for the S3 backend now only accept exactly true or false. The previous behavior treated any non-empty string as true. If you relied on setting these to values like 1, yes, or enabled, update them before upgrading.

Provider Installation Order in init

Provider installation was internally refactored in this release. The order of operations during init has changed, and two new log messages replace one existing message (initializing_provider_plugin_message). If you parse Terraform init logs programmatically, update your parsers accordingly. End-user behavior is otherwise unchanged.

What Experimental Features Are Available in Terraform 1.15 Alpha Builds?

These features are only available in alpha builds and are not part of stable 1.15 releases.

  • Deferred actions: Pass -allow-deferral to terraform plan to allow count and for_each in module, resource, and data blocks to have unknown values at plan time. Providers can then react more flexibly to unknowns. This targets cases where full evaluation is not possible until apply.
  • terraform test cleanup: A new command that automatically cleans up local state files left behind by failed test cleanup operations. Without this, failed test runs could leave state files in .terraform/ requiring manual removal.
  • Backend blocks in test run blocks: Test authors can now specify a backend block inside a run block in .tftest.hcl files. This loads existing state from a remote backend instead of starting from empty state, enabling tests against long-lived infrastructure.
  • skip_cleanup in test files: A new skip_cleanup attribute tells terraform test to preserve state files produced by the affected run blocks. Those files are written to .terraform/ and can then be cleaned up manually or via terraform test cleanup.

FAQ

Can I use var.something in the source attribute of a module block in 1.15?
Yes, this is now supported. Module source and version attributes accept variables and locals. You can pass variable values from the command line or .tfvars files as you normally would. Most Terraform commands have been updated to resolve these values before processing module sources.

What happens if I set AWS_USE_FIPS_ENDPOINT=1 with the S3 backend after upgrading to 1.15?
Terraform will no longer treat 1 as truthy. Only the exact string true enables FIPS endpoints now. Set the variable to true explicitly, or Terraform will behave as if FIPS is disabled. This aligns with the AWS SDK for Go behavior.

Does the new deprecated attribute on variables cause errors or just warnings?
It produces warnings, not errors. Callers can still pass values to deprecated variables and the plan will proceed. The intent is to give module consumers advance notice without breaking their workflows immediately. There is no automatic enforcement timeline built in -- that is up to the module author to manage through module versioning.

Is the convert() function safe to use with complex types like object and list?
Yes. The function accepts full type expressions, including list(string), map(number), object({ ... }), and so on. If the value cannot be converted to the target type, Terraform raises an error at plan time rather than silently producing a wrong value. In practice, it is most useful when consuming outputs from dynamic sources where the type is ambiguous.

Does the backend block validation in terraform validate require running terraform init first?
Yes, in most cases. Backend validation checks that the backend type is recognized and that its required attributes are present -- but for remote backends, the check still requires the provider plugins installed by init to be present. The improvement here is that validate now actively inspects the backend block instead of skipping it, which surfaces configuration errors earlier in local development workflows.

Releases In Branch 1.15

VersionRelease date
1.15.919 Aug 2026
(1 month ago)
1.15.808 Jul 2026
(3 months ago)
1.15.724 Jun 2026
(3 months ago)
1.15.610 Jun 2026
(4 months ago)
1.15.527 May 2026
(4 months ago)
1.15.420 May 2026
(4 months ago)
1.15.313 May 2026
(5 months ago)
1.15.206 May 2026
(5 months ago)
1.15.101 May 2026
(5 months ago)
1.15.029 Apr 2026
(5 months ago)
1.15.0-rc428 Apr 2026
(5 months ago)
1.15.0-rc322 Apr 2026
(5 months ago)
1.15.0-rc215 Apr 2026
(6 months ago)
1.15.0-rc109 Apr 2026
(6 months ago)
1.15.0-beta201 Apr 2026
(6 months ago)
1.15.0-beta118 Mar 2026
(6 months ago)
1.15.0-alpha2026030404 Mar 2026
(7 months ago)
1.15.0-alpha2026021818 Feb 2026
(7 months ago)
1.15.0-alpha2026020404 Feb 2026
(8 months ago)