Terraform Cert Guide Chapter 9: How Terraform Stacks Bring Everything Together

Chapter 9 is where the pieces from earlier chapters finally click together. You learned about modules. You learned about configuration files. Now you take those modules, combine them, and deploy real infrastructure at scale. That’s what Terraform stacks are about.

What Is a Terraform Stack?

The book opens with a scenario. You and your colleague John need to deploy 50 VMs, 20 virtual networks, 10 web apps, and 5 function apps in Azure. That’s a lot of infrastructure. How do you manage all of that without losing your mind?

John’s answer: write Terraform modules for each resource type, publish them to GitHub or Terraform Registry, then combine those modules into stacks.

A Terraform stack is just one or more modules combined together with environment-specific input values. That’s it. You already know modules are reusable. Stacks let you group them into a complete infrastructure deployment that you can run with a single terraform apply.

Think of it like cooking. Modules are your prepped ingredients. A stack is the actual recipe that brings them together into a finished meal.

The Three-Layer Pattern

Every cloud example in this chapter follows the same structure:

  1. Modules - individual, reusable resource definitions (VPC, subnet, storage, etc.)
  2. Stacks - a main.tf that references multiple modules together
  3. Stacks of stacks - a wrapper that consumes an entire stack as a single module

That third layer sounds weird at first. Why would you wrap a stack inside another module call? The answer is simple: when you need to deploy the same infrastructure to dev, test, and prod, stacks of stacks let you reuse everything without declaring the same variables three times. You just point to the stack directory and pass different .tfvars files for each environment.

Building a GCP Stack

The book walks through creating four GCP modules: vpc, subnet, route, and storage. Each module lives in its own directory with the standard three files: main.tf, variables.tf, and outputs.tf.

The VPC module is straightforward. It creates a google_compute_network resource with configurable name, MTU, routing mode, and project ID. All values come from input variables so the module stays reusable.

The subnet module is more interesting. It uses for_each with a locals block to iterate over a list of subnets. This means you can deploy hundreds of subnets by just adding entries to your .tfvars file. The module also uses dynamic blocks for flow log configuration and lookup functions for optional values. If you’re not comfortable with for_each, lookup, and dynamic blocks, go back to Chapter 4. Those concepts do the heavy lifting here.

The stacks directory brings all four modules together in a single main.tf:

module "vpc" {
  source   = "github.com/example/modules//vpc?ref=v1.12"
  vpc_name = var.vpc_name
  # ... other variables
}

module "subnet" {
  source     = "github.com/example/modules//subnet?ref=v1.13"
  vpc_name   = var.vpc_name
  subnets    = var.subnets
  depends_on = [module.vpc.id]
}

module "routes" {
  source     = "github.com/example/modules//route?ref=v1.10"
  vpc_name   = var.vpc_name
  depends_on = [module.vpc.id]
}

module "storage" {
  source       = "github.com/example/modules//storage?ref=v1.11"
  stg_name     = var.stg_name
  storage_class = var.storage_class
}

Notice the depends_on on subnet and routes. They need the VPC to exist first. Storage is independent so it can be created in parallel.

Then the stacks_of_stacks directory wraps the entire stack:

module "gcp_stacks" {
  source   = "../stacks"
  vpc_name = var.vpc_name
  subnets  = var.subnets
  # ... all other variables passed through
}

When you run terraform init here, Terraform downloads every module from GitHub, chains them all together, and you’re ready to plan and apply.

Building an AWS Stack

The AWS example follows the exact same pattern. Three modules this time: vpc-subnet (combined into one), and s3. Same directory structure: modules, stacks, stacks_of_stacks.

The stack combines the VPC and S3 modules:

module "vpc" {
  source    = "github.com/example/modules//vpc-subnet?ref=v1.14"
  cidr_block = var.cidr_block
  vpc_name   = var.vpc_name
  # ... networking variables
}

module "s3" {
  source      = "github.com/example/modules//s3?ref=v1.14"
  bucket_name = var.bucket_name
  bucket_acl  = var.bucket_acl
  depends_on  = [module.vpc.id]
}

Running terraform apply -auto-approve creates the VPC, subnet, and S3 bucket. The book shows it completing with “3 added, 0 changed, 0 destroyed.”

One thing the book calls out here: when you build stacks of stacks, validating specific outputs gets harder. Your stack contains many different modules, and tracing which output comes from where can get tricky. Keep that in mind when designing your output blocks.

Building an Azure Stack

No surprises with Azure. The book creates modules for storage and webapp (App Service). Same three-layer pattern. Same directory structure.

The stack of stacks for Azure passes variables for resource groups, storage accounts, app configuration, connection strings, and more:

module "azure_stacks" {
  source               = "../stacks"
  resource_group_name  = var.resource_group_name
  storage_account_name = var.storage_account_name
  app_config           = var.app_config
  # ... other variables
}

After terraform init downloads the modules and terraform apply runs, you get your storage account and web app deployed in Azure. The book shows a screenshot of the resources appearing in the Azure portal.

Why Stacks Matter

The real value of stacks becomes obvious when you zoom out. Without stacks, you’d be copying and pasting module blocks across projects, redeclaring the same variables everywhere, and hoping everything stays in sync.

With stacks, you get:

  • Less code duplication. Define your infrastructure once, use it everywhere.
  • Simpler variable management. Stacks of stacks reduce variable re-declaration.
  • Consistent deployments. Same stack, different .tfvars files for each environment.
  • Easier scaling. Need to add 50 more subnets? Update the tfvars file, not the code.

The pattern is cloud-agnostic too. GCP, AWS, Azure: the structure is identical. The only things that change are the provider-specific resource types and their arguments.

Key Takeaways for the Cert Exam

A few things from this chapter that are likely to show up on the certification:

  • Stacks = modules combined with environment-specific values. That’s the definition.
  • terraform init downloads modules from GitHub. If your modules are sourced from a remote repo, init fetches them.
  • terraform fmt -recursive fixes formatting across all your stack files.
  • Version pinning matters. If you don’t pin module versions (like ?ref=v1.12), Terraform grabs the latest. If the latest version has breaking changes, your stack breaks. Always pin your versions.
  • Variables can be passed via .tfvars, .auto.tfvars, or .tfvars.json. If you forget to provide a value, Terraform will prompt you at runtime.

My Take

This chapter is practical and to the point. If you understood modules from earlier chapters, stacks are just the logical next step. The three-layer pattern (modules, stacks, stacks of stacks) is a solid way to organize any Terraform project, regardless of cloud provider.

The one thing I wish the book spent more time on is testing. When you have stacks of stacks with complex variable chains, a typo in a variable name can cascade through multiple layers before you catch it. In real-world projects, adding terraform validate and terraform plan into your CI pipeline catches these issues early.

But for the certification exam, this chapter gives you what you need. Understand what stacks are, know how to combine modules, and remember the version pinning gotcha. You’ll be fine.


Previous: Chapter 8: Configuration Files

Next: Chapter 10: Cloud and Enterprise


This is part of a series retelling “HashiCorp Infrastructure Automation Certification Guide” by Ravi Mishra (Packt, 2021). For the full text, grab the book - ISBN: 978-1-80056-597-5.

About

About BookGrill.net

BookGrill.net is a technology book review site for developers, engineers, and anyone who builds things with code. We cover books on software engineering, AI and machine learning, cybersecurity, systems design, and the culture of technology.

Know More