← All articles
Published Sep 5, 20253 min read

Stop Building Terraform God Modules

Why modules with 40 inputs and passthrough variables slow teams down—and how to design reusable building blocks instead.

Gabriel Levasseur

Gabriel Levasseur

Founder

Stop Building Terraform God Modules

Every platform team inherits at least one "god module"—a single module that promises to spin up the VPC, networking, security groups, cluster, autoscaling, logging, and dashboards all at once. It ships with pages of inputs to toggle features, plus passthrough variables for every nested resource. Consumers end up pasting whole sub-resource configs just to get a simple service out the door. The result? Nobody knows which inputs are required, drift sneaks in, and the module becomes a liability.

Recognize the god-module pattern

  • Feature flag soup: A forest of booleans such as enable_alb, enable_autoscaling, or create_private_dns. Turning one on silently creates other resources.
  • Config passthroughs: Catch-all objects like security_group_config or task_definition_config that demand full AWS argument maps.
  • Memory-only defaults: Inputs with null defaults that force callers to discover intent by reading the internals.
  • Slow, scary plans: Terraform redraws half your infrastructure when a single toggle flips because the module has no clear boundaries.

Why it hurts consumers

God modules are hard to document, test, and reason about. Callers can't tell which combinations of flags are safe, so they cargo-cult the last working config. Reviewers can't confidently approve changes because every plan touches critical infrastructure. The platform team becomes the support desk for deciphering dozens of optional arguments.

Guardrail

If a module requires callers to pass entire nested resource configs "just in case," it's not an abstraction—it's a thin wrapper over raw Terraform that hides where the risk lives.

When a monolith might be okay

The only time a large module works is when it is extremely opinionated: one workload, one golden path, and tight defaults the team won't override. You're effectively vendoring a platform feature, not shipping a building block. The moment consumers need switches and passthroughs, the abstraction starts to crumble.

Prefer composable building blocks

Instead of a single kitchen-sink module, think in terms of modules that represent concrete capabilities. For example:

  • ecs-service for the service definition and task scheduling.
  • ecs-service-scaling for autoscaling policies tied to CloudWatch metrics.
  • alb for listeners, target groups, and security groups.
  • private-dns and public-dns for Route53 zones and records.

These modules snap together so teams can plug-and-play what they need. Need an internal batch worker? Skip the ALB module and attach only scaling plus private DNS. Launching a public API? Compose the ALB and public DNS modules. Each piece remains testable, documented, and owned by the team closest to the concern.

How to unwind the monolith

  1. Inventory usage: Use terraform-config-inspect or repo search to list every caller and the inputs they set.
  2. Slice by intent: Group inputs into concerns—networking, compute, observability—and define a module per intent.
  3. Codify defaults: Bake the platform's guardrails (encryption, logging, tagging) into each module so callers get them without extra flags.
  4. Expose escape hatches through composition: Offer extension points such as attaching additional security groups or extra listeners via module outputs, not extra booleans on the base module.

Document and test each slice

Publish an examples/ folder for each module and run them in CI (Terratest or terraform test). Consumers get copy-pastable patterns, and you gain confidence that the modules compose without surprises.

By retiring god modules, your Terraform library becomes easier to reason about. Engineers grab the building blocks that fit their intent, and platform teams evolve smaller, purpose-built components. Cora's graph view will reflect that clarity immediately—modular infrastructure turns sprawling spaghetti into concise, understandable architecture.

Audit your modules with Cora

Ready to see Cora in action? Jump into the product experience tailored to this article.

Audit your modules with Cora

Keep reading

View all