← All articles
Published Sep 18, 20253 min read

Design Terraform Modules for the Right Consumer

Avoid fake abstractions by tailoring modules to the engineers who actually use them—and handling edge cases the right way.

Gabriel Levasseur

Gabriel Levasseur

Founder

Design Terraform Modules for the Right Consumer

As a platform engineer, every Terraform module you publish is a product. Two very different audiences depend on that product:

  • Other infrastructure engineers who want building blocks they can wire together however they need.
  • Product engineers who just want to ship features and expect a paved path.

If you blur those audiences, you end up with abstractions that satisfy no one. Let’s clarify who you’re supporting and shape your modules accordingly.

Know which audience you’re serving

Start every module with a short README clause: "Primary consumer: product engineers" or "Primary consumer: platform networking". That declaration unlocks two mindsets:

ConsumerWhat they needHow your module should respond
Product engineersOutcomes, not infrastructure triviaHide the knobs, ship strong defaults, and wrap common tasks in opinionated interfaces.
Infrastructure engineersFine-grained control with guardrailsExpose detailed inputs, but still enforce policy and sensible defaults.

The clearer you are up front, the easier it becomes to decide what goes inside—and what deserves a separate module.

Designing modules for product engineers

Product engineers shouldn’t learn VPC trivia just to get an HTTPS endpoint. Give them an interface that reads like their intention:

  • Ship a real abstraction. Expose the handful of inputs that represent the outcome—service_name, container_port, domain_name. Everything else should be an opinionated default.
  • Be boldly opinionated. If 90% of teams should enable access logs, flip them on by default. Document how to opt out instead of forcing every team to make the same decision.
  • Duplicate when necessary. It’s okay to publish ecs-web-service and ecs-worker-service if the ergonomics differ. Avoid the temptation to combine them behind service_mode = "worker" flags that confuse consumers.
  • Compose behind the scenes. Build your higher-level module by stitching together smaller primitives (networking, logging, alarms). You can swap pieces later without breaking the contract.

The goal: a product engineer copies 10 lines, sets three variables, and gets a working service on day one.

Designing modules for other infrastructure engineers

When you’re building for peers on the infra team, you can expose more surface area—but discipline still matters.

  • Stick to best practices. Enforce tagging, encryption, and guardrails even if you expose granular inputs. Colleagues expect secure defaults, not a raw AWS mirror.
  • Favor composable building blocks. Provide modules like alb, alb-logging, or aurora-cluster that slot together cleanly. Infra engineers can assemble tailored stacks without cracking the module internals.
  • Evolve with versioning. Because these modules expose sharper edges, publish clear upgrade guides and semantic version bumps when you add or remove inputs.

Think of these modules as a curated toolbox—flexible, but still safe.

Favor composition over kitchen-sink toggles

Whether you’re targeting product or platform engineers, avoid the boolean flag explosion. Composable modules keep contracts crisp:

module "alb" {
  source = "../modules/alb"
  name   = var.service_name
}

module "alb_logging" {
  source  = "../modules/alb-logging"
  alb_arn = module.alb.arn
  enabled = var.enable_logging
}

Wrap up

Great Terraform libraries feel intentional. Decide who you’re serving, shape the abstraction to that audience, and lean on composable building blocks so you can evolve quickly. Do that, and your modules become a force multiplier for every engineering team—not another layer of YAML to debug.

Share your module library with Cora

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

Share your module library with Cora

Keep reading

View all