Bird
Raised Fist0
Terraformcloud~15 mins

Module versioning in Terraform - Deep Dive

Choose your learning style10 modes available
Overview - Module versioning
What is it?
Module versioning in Terraform means managing different versions of reusable code packages called modules. These modules contain infrastructure code that can be shared and reused across projects. Versioning helps track changes and ensures that the right module version is used when building infrastructure. It prevents unexpected changes from breaking your setup.
Why it matters
Without module versioning, teams would struggle to keep infrastructure consistent and stable. Changes in a module could break deployments or cause downtime if not controlled. Versioning allows safe updates, rollback to previous states, and collaboration across teams. It brings reliability and predictability to infrastructure management.
Where it fits
Before learning module versioning, you should understand basic Terraform concepts like resources, modules, and state. After mastering versioning, you can explore advanced topics like module registries, dependency management, and CI/CD integration for infrastructure.
Mental Model
Core Idea
Module versioning is like using specific editions of a recipe book to ensure your dish always tastes the same, even if the recipe changes over time.
Think of it like...
Imagine you have a cookbook that your family uses to bake a cake. Over time, the recipe changes slightly. If you always use the latest recipe without tracking versions, your cake might taste different each time. By keeping track of recipe editions (versions), you can choose which cake version to bake and avoid surprises.
┌───────────────┐       ┌───────────────┐       ┌───────────────┐
│ Module v1.0   │──────▶│ Module v1.1   │──────▶│ Module v2.0   │
│ (Initial)     │       │ (Bug fixes)   │       │ (New features)│
└───────────────┘       └───────────────┘       └───────────────┘
       ▲                      ▲                      ▲
       │                      │                      │
   Project A              Project B              Project C
  uses v1.0              uses v1.1              uses v2.0
Build-Up - 7 Steps
1
FoundationWhat is a Terraform module
🤔
Concept: Introduce the idea of a module as a reusable infrastructure code package.
A Terraform module is a folder with Terraform files that define resources. Instead of writing the same code repeatedly, you create a module once and use it many times. Modules help organize and reuse infrastructure code.
Result
You understand that modules package infrastructure code for reuse.
Knowing what a module is helps you see why versioning modules matters for consistency.
2
FoundationWhy reuse modules matters
🤔
Concept: Explain the benefits of reusing modules across projects.
Reusing modules saves time and reduces errors. If you fix a bug or add a feature in a module, all projects using it can benefit. But without version control, changes might break some projects unexpectedly.
Result
You see the value of modules but also the risk of uncontrolled changes.
Understanding reuse risks sets the stage for why versioning is essential.
3
IntermediateHow Terraform handles module versions
🤔Before reading on: do you think Terraform automatically updates modules to the latest version or keeps the version you specify? Commit to your answer.
Concept: Terraform allows specifying exact module versions to control which code is used.
When you use a module from a source like the Terraform Registry or a Git repository, you can specify a version or tag. Terraform downloads that exact version. It does not update automatically unless you change the version in your configuration.
Result
You learn to pin module versions to avoid unexpected changes.
Knowing Terraform locks module versions prevents surprise infrastructure changes.
4
IntermediateSpecifying versions in module source
🤔Before reading on: do you think you specify module versions inside the module code or in the calling configuration? Commit to your answer.
Concept: Module versions are specified in the calling Terraform configuration, not inside the module itself.
In your Terraform code, when you declare a module block, you add a version argument if the source supports it. For example, from the Terraform Registry: module "example" { source = "hashicorp/consul/aws" version = "~> 0.1" } This tells Terraform to use versions compatible with 0.1.x.
Result
You can control which module version your project uses by specifying it in your configuration.
Understanding where to specify versions helps you manage dependencies effectively.
5
IntermediateSemantic versioning basics
🤔Before reading on: do you think version 1.2.0 is a bigger change than 2.0.0? Commit to your answer.
Concept: Terraform modules use semantic versioning (semver) to communicate changes clearly.
Semantic versioning uses three numbers: MAJOR.MINOR.PATCH. MAJOR changes break compatibility, MINOR adds features without breaking, PATCH fixes bugs. For example, 2.0.0 is a bigger change than 1.2.0 because it may break compatibility.
Result
You understand how version numbers signal the type of changes in a module.
Knowing semver helps you decide when it's safe to upgrade modules.
6
AdvancedManaging module upgrades safely
🤔Before reading on: do you think upgrading a module version always requires manual testing or can it be fully automated? Commit to your answer.
Concept: Upgrading modules requires careful testing and sometimes manual review to avoid breaking infrastructure.
When you want to upgrade a module version, you update the version in your configuration and run terraform init to download it. Then you run terraform plan to see what changes will happen. This helps catch unexpected changes before applying. Automated tests and CI pipelines can help but manual review is often needed.
Result
You learn the process to safely upgrade modules without breaking infrastructure.
Understanding upgrade risks and testing prevents costly downtime.
7
ExpertVersion constraints and dependency resolution
🤔Before reading on: do you think Terraform resolves module versions globally across all modules or individually per module? Commit to your answer.
Concept: Terraform uses version constraints to resolve compatible module versions, but each module's version is managed independently.
You can specify version constraints like ">= 1.0, < 2.0" to allow flexibility. Terraform picks the newest version that fits constraints. However, Terraform does not resolve versions globally across all modules like some package managers. Each module's version is independent, so conflicts must be managed manually.
Result
You understand how Terraform handles version constraints and the limits of its dependency resolution.
Knowing Terraform's version resolution limits helps avoid complex dependency conflicts.
Under the Hood
Terraform modules are downloaded from their source (Registry, Git, local path) during terraform init. When a version is specified, Terraform fetches that exact version, storing it in the local module cache. The module code is then used to build the resource graph. Terraform does not dynamically update modules during apply; it relies on the locked version in configuration and state files.
Why designed this way?
Terraform was designed to prioritize infrastructure stability and predictability. Automatically updating modules could cause unexpected changes and downtime. By requiring explicit version specification and manual upgrades, Terraform gives users control over when and how infrastructure changes happen. This design trades convenience for safety.
┌───────────────┐       ┌───────────────┐       ┌───────────────┐
│ Terraform     │       │ Module Source │       │ Local Module  │
│ Configuration │──────▶│ (Registry/Git)│──────▶│ Cache (Version│
│ (version pin) │       │               │       │  stored here) │
└───────────────┘       └───────────────┘       └───────────────┘
        │                                              │
        │                                              ▼
        │                                     ┌─────────────────┐
        │                                     │ Terraform Plan & │
        │                                     │ Apply using      │
        │                                     │ pinned version   │
        │                                     └─────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does Terraform automatically update modules to the latest version if you don't specify a version? Commit yes or no.
Common Belief:Terraform always uses the latest module version automatically.
Tap to reveal reality
Reality:Terraform uses the latest version only if no version is specified, but this is not recommended. Specifying versions pins the module to a known state.
Why it matters:Assuming automatic updates can cause unexpected infrastructure changes and failures.
Quick: Can you specify module versions inside the module code itself? Commit yes or no.
Common Belief:Module versions are declared inside the module's own Terraform files.
Tap to reveal reality
Reality:Module versions are specified by the user in the calling configuration, not inside the module code.
Why it matters:Misunderstanding this leads to confusion about how to control module versions.
Quick: Is semantic versioning just a naming convention without practical impact? Commit yes or no.
Common Belief:Semantic versioning is just a label and does not affect module compatibility.
Tap to reveal reality
Reality:Semantic versioning communicates compatibility and guides safe upgrades.
Why it matters:Ignoring semver can cause breaking changes to be introduced unknowingly.
Quick: Does Terraform resolve all module versions globally to avoid conflicts? Commit yes or no.
Common Belief:Terraform automatically resolves all module versions globally like some package managers.
Tap to reveal reality
Reality:Terraform manages each module version independently and does not resolve conflicts globally.
Why it matters:Expecting global resolution can lead to dependency conflicts and deployment failures.
Expert Zone
1
Terraform's module cache stores downloaded versions locally, speeding up repeated runs but requiring manual cache clearing to update versions.
2
Using version constraints with care allows flexibility but can introduce subtle incompatibilities if not tested thoroughly.
3
Private module registries and Git tags can be used to manage custom module versions securely in enterprise environments.
When NOT to use
Module versioning is not a substitute for proper testing and validation. In cases where infrastructure must always use the absolute latest features, consider continuous integration pipelines with automated testing rather than relying solely on version pins.
Production Patterns
In production, teams use strict version pinning combined with automated terraform plan and apply pipelines. They maintain a module registry with approved versions and use semantic versioning to communicate changes. Rollbacks are done by reverting to previous module versions in configuration.
Connections
Semantic Versioning
Module versioning builds on semantic versioning principles.
Understanding semantic versioning outside Terraform helps grasp how module versions signal compatibility and change impact.
Software Package Management
Module versioning in Terraform is similar to package versioning in software development.
Knowing how package managers like npm or pip handle versions clarifies Terraform's approach to module version control.
Supply Chain Management
Both manage versions and dependencies to ensure consistent delivery of goods or code.
Recognizing versioning as a supply chain problem highlights the importance of tracking and controlling changes to avoid disruptions.
Common Pitfalls
#1Not specifying module versions leads to unpredictable infrastructure changes.
Wrong approach:module "example" { source = "hashicorp/consul/aws" }
Correct approach:module "example" { source = "hashicorp/consul/aws" version = "~> 0.1" }
Root cause:Assuming Terraform will always use a stable module version without explicit version pinning.
#2Specifying version inside the module code instead of the calling configuration.
Wrong approach:# Inside module code variable "version" { default = "1.0.0" }
Correct approach:# In calling configuration module "example" { source = "hashicorp/consul/aws" version = "1.0.0" }
Root cause:Confusing module code with module usage context.
#3Ignoring semantic versioning and upgrading major versions without testing.
Wrong approach:module "example" { source = "hashicorp/consul/aws" version = "2.0.0" } # Upgraded without review
Correct approach:module "example" { source = "hashicorp/consul/aws" version = "~> 1.1" } # Stays in compatible range
Root cause:Not understanding the impact of major version changes on compatibility.
Key Takeaways
Terraform module versioning controls which exact module code is used, ensuring stable infrastructure.
Specifying module versions in the calling configuration prevents unexpected changes and downtime.
Semantic versioning guides safe upgrades by signaling compatibility and change types.
Terraform does not automatically update modules; manual version changes and testing are required.
Understanding module versioning is essential for reliable, maintainable infrastructure as code.

Practice

(1/5)
1. What is the main purpose of specifying a version when using a Terraform module from a registry?
easy
A. To speed up Terraform plan execution
B. To enable local module usage
C. To automatically update the module to the latest version
D. To keep your infrastructure stable by locking the module version

Solution

  1. Step 1: Understand module versioning purpose

    Specifying a version locks the module to a specific release, preventing unexpected changes.
  2. Step 2: Compare options

    Only locking the version ensures stability; automatic updates or speed improvements are not guaranteed by versioning.
  3. Final Answer:

    To keep your infrastructure stable by locking the module version -> Option D
  4. Quick Check:

    Module versioning = Stability [OK]
Hint: Version locks module to prevent unexpected changes [OK]
Common Mistakes:
  • Thinking version speeds up execution
  • Assuming version auto-updates modules
  • Confusing local modules with versioned modules
2. Which of the following is the correct syntax to specify a module version from the Terraform Registry?
easy
A. module "example" { source = "registry/module" version = "1.2.0" }
B. module "example" { source = "registry/module" ver = "1.2.0" }
C. module "example" { source = "registry/module" version: "1.2.0" }
D. module "example" { source = "registry/module" v = "1.2.0" }

Solution

  1. Step 1: Recall correct version attribute

    The correct attribute to specify module version is version with an equals sign.
  2. Step 2: Check syntax correctness

    module "example" { source = "registry/module" version = "1.2.0" } uses correct attribute and syntax; others use incorrect attribute names or syntax.
  3. Final Answer:

    module "example" { source = "registry/module" version = "1.2.0" } -> Option A
  4. Quick Check:

    Correct attribute is version = "x.y.z" [OK]
Hint: Use 'version = "x.y.z"' exactly for module versions [OK]
Common Mistakes:
  • Using 'ver' or 'v' instead of 'version'
  • Using colon instead of equals sign
  • Omitting quotes around version number
3. Given this Terraform module block:
module "network" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "3.0.0"
}

What happens if a newer version 3.1.0 is released and you run terraform init without changing the version?
medium
A. Terraform upgrades the module to version 3.1.0 automatically
B. Terraform uses version 3.0.0 and does not upgrade automatically
C. Terraform throws an error about version mismatch
D. Terraform ignores the version and uses the latest

Solution

  1. Step 1: Understand version locking behavior

    Specifying version "3.0.0" locks the module to that exact version.
  2. Step 2: Effect of terraform init

    Running terraform init downloads the locked version; it does not upgrade unless version is changed.
  3. Final Answer:

    Terraform uses version 3.0.0 and does not upgrade automatically -> Option B
  4. Quick Check:

    Locked version stays fixed until changed [OK]
Hint: Locked version stays fixed unless manually updated [OK]
Common Mistakes:
  • Assuming terraform init upgrades modules automatically
  • Expecting errors on version mismatch
  • Thinking latest version is always used
4. You have this module block:
module "db" {
  source = "git::https://github.com/example/db-module.git"
}

You want to use a specific version tag v1.4.2. What is missing?
medium
A. Add tag = "v1.4.2" inside the block
B. Add version = "v1.4.2" inside the block
C. Add ?ref=v1.4.2 to the source URL
D. Nothing, it uses latest by default

Solution

  1. Step 1: Understand versioning for Git modules

    Git modules use URL query parameter ?ref= to specify version or tag.
  2. Step 2: Identify correct way to specify tag

    Adding ?ref=v1.4.2 to source URL locks module to that tag.
  3. Final Answer:

    Add ?ref=v1.4.2 to the source URL -> Option C
  4. Quick Check:

    Git module version = source URL + ?ref=tag [OK]
Hint: Use ?ref=tag in Git source URL for versioning [OK]
Common Mistakes:
  • Using version attribute for Git modules
  • Using tag attribute which does not exist
  • Assuming latest is always used without specifying ref
5. You have a local module at ./modules/app and a remote module from the registry. You want to ensure only the remote module uses versioning. How should you configure the modules?
hard
A. Specify version only for the remote module; omit for local module
B. Specify version for both local and remote modules
C. Specify version only for the local module
D. Omit version for both modules

Solution

  1. Step 1: Recall versioning rules for local modules

    Local modules do not support versioning; version attribute is ignored or causes error.
  2. Step 2: Apply version only to remote modules

    Only remote modules from registries or Git support versioning and require version locking.
  3. Final Answer:

    Specify version only for the remote module; omit for local module -> Option A
  4. Quick Check:

    Version only for remote modules [OK]
Hint: Version attribute only for remote modules, never local [OK]
Common Mistakes:
  • Adding version to local modules causing errors
  • Omitting version for remote modules causing instability
  • Confusing local and remote module versioning rules
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard