Skip to main content

Command Palette

Search for a command to run...

Terraform Stacks: The Opinionated Deep Dive Nobody Warned You About

Updated
5 min read
Terraform Stacks: The Opinionated Deep Dive Nobody Warned You About

Terraform Stacks: The Opinionated Deep Dive Nobody Warned You About

Pull up a chair.

This is one of those topics where the official docs smile politely at you while quietly hiding the knife behind their back.

I’m going to be opinionated on purpose.

When people talk about Terraform stacks, the industry default still looks like this:

“Break everything into lots of small stacks (or workspaces), wire them together with remote state, and let teams own their little slice.”

It sounds mature. Scalable. Enterprise-ready.

I disagree.

Strongly.

I’ll argue that a single, orchestration-first stack with thin, boring modules is superior to the “many independent stacks stitched together with data sources” approach most teams adopt.

Terraform doesn’t force these architectural choices — it simply makes the consequences of poor boundaries impossible to ignore.


Two mental models. Only one tells the whole truth.


What a “stack” really is (not what the docs say)

Terraform doesn’t force these decisions. It simply refuses to hide their consequences. A Terraform stack is not a folder.
It’s not a workspace.
It’s not a module.

A stack is a decision boundary.

It defines:

  • what gets planned together

  • what gets applied together

  • what can fail together

  • what you mentally reason about at 2 a.m.

If that boundary is wrong, no amount of terraform fmt will save you.


A stack is where decisions, failure, and responsibility meet.


The industry standard: many small stacks

This is the popular model:

  • One stack for networking

  • One stack for IAM

  • One stack per service

  • One stack per environment

  • Remote state everywhere

On paper, it looks like microservices for infrastructure.

In practice?

It’s like running a restaurant where:

  • one team preps vegetables

  • another cooks

  • a third plates

  • a fourth serves

  • and none of them are allowed to talk directly

Everything goes through tickets.

You can run a kitchen like that.

You just won’t survive dinner rush.


The superior approach: orchestration-first stacks

Here’s the approach I recommend far more often than people expect:

One stack owns the lifecycle

  • Environment-level stack (dev, staging, prod)

  • It orchestrates everything that must change together

  • Modules are thin, dumb, and reusable

  • No cross-stack remote state for core dependencies

Think of it like a head chef.

The chef doesn’t chop every onion personally.
But they do decide:

  • when dishes go out

  • what gets cooked together

  • what happens when something is late

Terraform stacks should behave the same way.


Why this works better in the real world

Planning is where truth lives

Most infrastructure failures don’t happen at apply time.
They happen because the plan lied.

With many small stacks:

  • each plan is locally correct

  • the overall system is globally wrong

One stack. One plan. One truth.

If networking, compute, and permissions change together, you want to see the blast radius upfront.

Hiding it behind five pipelines doesn’t make it safer.
It makes it invisible.


Humans reason in stories, not graphs

Docs assume engineers think in dependency graphs.

They don’t.

They think in narratives:

“We’re adding a new service that needs a load balancer, IAM role, and database.”

That story fits naturally in a single orchestration stack.

Splitting it across stacks forces the reader to mentally replay a detective novel just to understand why an output exists.

If understanding your infra requires a whiteboard, your stack boundary is wrong.


Thin modules age better than clever stacks

People love clever modules.

They age like milk.

Thin modules:

  • create resources

  • accept primitives

  • return boring outputs

The intelligence belongs in the stack.

Business logic changes faster than infrastructure primitives.
Your stack is allowed to change.
Your modules should feel embarrassingly simple.


A real-world analogy: load balancing as a kitchen

Load balancing is often explained with diagrams.

Here’s a better analogy.

A busy restaurant doesn’t assign customers directly to chefs.

There’s a host.

The host:

  • sees the whole room

  • knows which tables are overloaded

  • adapts in real time

A single orchestration stack is that host.

Multiple disconnected stacks are customers wandering into the kitchen shouting orders and hoping someone listens.


“But what about team autonomy?”

This is where people get emotional.

They hear “single stack” and think:

“Centralized control. Bottlenecks. A platform team saying no.”

That’s not a stack problem.
That’s an ownership problem.

You can:

  • keep code ownership per module

  • enforce review boundaries

  • delegate responsibility

without fragmenting the lifecycle.

Autonomy without coordination is just chaos with better branding.


The Ugly Truth (the part many techies and contents avoid)

Let’s be honest.


*Terraform makes dependencies explicit — which means poor boundaries become visible faster. *


Single stacks have real downsides

  • Plans get big

  • Applies take longer

  • One mistake can block multiple teams

  • State files become precious artifacts

You will feel this pain.

But here’s the part people won’t say out loud:

You are already paying these costs.

You’re just paying them in outages, debugging time, and human stress instead of CI minutes.

Remote state is a powerful tool — but it doesn’t remove coupling, it postpones when you feel it.


When many stacks actually make sense

I’m not dogmatic.

Split stacks when:

  • lifecycles are genuinely independent

  • failure domains must be isolated

  • regulatory boundaries demand it

  • applies cannot safely happen together

If two things always change together, they belong together.


The mentor advice I wish I got earlier

Design Terraform stacks the way you’d design incident response.

Ask yourself:

  • “What do I want to see in one plan?”

  • “What should never drift independently?”

  • “What failure would wake me up at night?”

Then draw your boundaries there.

Not where the docs say.
Not where the trend points.

Where reality lives.

Author’s note: This post is intentionally opinionated and drawn from real production experience. It’s not a critique of Terraform as a tool, but of common patterns teams adopt without revisiting their trade-offs. Terraform is doing exactly what it’s designed to do — making dependencies and boundaries explicit. The goal here is to encourage more deliberate stack design, not prescribe a single “correct” way to use Terraform. Happy terraforming!

#terraform #hashicorp

The HashiCorp Hustle

Part 1 of 12

"The HashiCorp Hustle" dives deep into the world of HashiCorp tools, empowering you to build, secure, and connect your infrastructure with confidence.

Up next

migrating 500 existing resources to Terraform

The real experiences nobody tells you about..!