Codenil

Mastering Terraform 1.15: Dynamic Module Sources and Deprecation Strategies

Published: 2026-05-19 01:49:42 | Category: Linux & DevOps

Overview

Terraform 1.15 introduces two powerful features that enhance module management: the ability to use dynamic sources via the const variable attribute, and a formal deprecation mechanism for module variables and outputs. These additions give practitioners greater flexibility in structuring configurations while maintaining clear upgrade paths. This guide walks through each feature step by step, with practical examples and pitfalls to avoid.

Mastering Terraform 1.15: Dynamic Module Sources and Deprecation Strategies

Prerequisites

Before diving in, ensure you have:

  • Terraform 1.15 or later installed. Verify with terraform version.
  • Basic familiarity with Terraform modules, variables, and outputs.
  • A text editor for writing configuration files.

Step-by-Step Instructions

1. Dynamic Module Sources with the const Attribute

In earlier versions, module sources had to be static strings. With Terraform 1.15, you can now use variables in module source paths – but only if those variables are decorated with the new const = true attribute. This attribute tells Terraform that the variable’s value is known at init time and never changes.

Declaring a const Variable

Add the const attribute to a variable block:

variable "folder" {
  type  = string
  const = true
}

Important: const cannot be combined with sensitive or ephemeral. These attributes are mutually exclusive because const variables must be plain text at init time.

Using const in Module Sources

Once declared, reference the variable directly in a module’s source:

module "zoo" {
  source = "./${var.folder}"
}

The source can be a local path, a registry path, or a remote URL – as long as the variable is declared as const, Terraform will resolve it during terraform init.

Nested Modules and Source Propagation

This functionality extends to nested modules, but only if each intermediate module explicitly declares the relevant variable with const = true. If a parent module passes down a variable that is not marked as const, Terraform will raise an error during init. Similarly, you cannot use a local value or a non-const variable in a module source; only const variables are allowed.

# Parent module passes folder to child
variable "folder" {
  const = true
}

module "child" {
  source = "./${var.folder}"
}

2. Deprecating Module Variables and Outputs

Module authors often need to phase out old interfaces. Terraform 1.15 adds a deprecated attribute to variable and output blocks, enabling you to mark them as deprecated and provide a migration message.

Deprecating a Variable

Inside your module’s .tf file, add the deprecated argument:

variable "bad" {
  type = string
  deprecated = "Please use 'good' instead; this variable will be removed in a future version."
}

When a user provides a value for this variable (via CLI arguments, .tfvars, or environment variables), Terraform emits a warning diagnostic during validation. No warning is shown if the variable is not set – only when it is actively used.

Deprecating an Output

Similarly, you can deprecate an output:

output "old" {
  value = module.example.result
  deprecated = "Use 'new' instead."
}

A warning appears whenever another configuration references this output, e.g., module.myModule.old.

Chaining Deprecated Outputs

To give users a smooth migration path, Terraform allows a deprecated output to reference another deprecated output. Only the outermost usage triggers a warning. Example:

# mod/main.tf
output "old" {
  value = "something"
  deprecated = "Use output 'new' instead."
}

# main.tf
module "myModule" {
  source = "./mod"
}

output "ancient" {
  value = module.myModule.old
  deprecated = "Stop using this entirely."
}

When the root module references module.myModule.old inside the ancient output, a single deprecation warning appears for ancient, not for old. This reduces noise while still guiding users to the final replacement.

Multiple Deprecation Diagnostics in One Configuration

Here’s a complete example that triggers warnings in several places:

# root/main.tf
variable "root" {
  deprecated = "This should no longer be used."
}

module "myModule" {
  source = "./mod"
  bad    = "not good"   # triggers deprecation warning for variable 'bad'
}

locals {
  moduleUsage = module.myModule.old   # triggers deprecation warning for output 'old'
}

The warnings appear during terraform validate and also when running other commands that trigger validation.

Common Mistakes

  • Using const with sensitive or ephemeral: These three attributes are mutually exclusive. If you attempt to combine them, Terraform will return an error.
  • Referencing non-const variables in module sources: Only variables explicitly marked const = true can be used in source. Using a regular variable or a local will cause an error at init.
  • Forgetting that deprecation warnings only fire during validation: Users might expect warnings during apply or plan, but deprecation diagnostics are emitted during the validation phase. Run terraform validate to see them.
  • Overlooking environment variable inputs: If a variable is deprecated, supplying it via TF_VAR_ also triggers the warning. This helps catch lingering values in CI/CD pipelines.
  • Assuming nested modules inherit const variables automatically: Each module in the chain must declare its own const variable; Terraform does not propagate the attribute implicitly.

Summary

Terraform 1.15 empowers you to create more dynamic and maintainable configurations. By using the const attribute on variables, you can build reusable modules that accept dynamic source paths without sacrificing init-time safety. The new deprecation attributes for variables and outputs provide a clear, automated way to signal end-of-life for module interfaces, reducing breakage and improving communication with users. Together, these features streamline module development and lifecycle management in Terraform.