← Back to portfolio

Building Reusable Terraform Modules That Teams Actually Use

TerraformIaCOCIDevOpsPlatform Engineering

Building a library of reusable Terraform modules is a common platform engineering goal. In practice, many modules go unused. Here is what separates the modules teams adopt from the ones they ignore.

The Modules That Work

The networking module. A module that creates a Virtual Cloud Network with public and private subnets, route tables, security lists, and a NAT gateway tends to get adopted quickly because it replaces hundreds of lines of Terraform with a short module invocation. The value is obvious and immediate.

The managed Kubernetes module. A module that provisions a managed Kubernetes cluster with node pools, RBAC, and monitoring integration gets adopted because getting the cloud-specific settings right from scratch requires deep knowledge that most engineers do not have.

The Modules That Fail

The "everything" module. A module that provisions an entire application stack (database, queues, compute, networking) rarely gets used because every team's stack is slightly different. When a module has dozens of input variables, teams spend more time reading its documentation than they would spend writing the Terraform themselves.

The logging module. A module that configures logging with sensible defaults often gets ignored because teams have already set up logging manually and do not want to import existing state.

What Makes a Module Adoptable

  1. It replaces genuine complexity. If the module saves a trivial amount of code, nobody cares. If it encodes tribal knowledge and replaces significant boilerplate, everyone cares.
  2. It has few required variables. Every variable is a decision the user has to make. Minimize decisions.
  3. It works with terraform plan on the first try. If a team has to debug the module before they can use it, they will write their own.
  4. It is versioned. Pin module versions in Terraform. Breaking changes in shared modules break every team simultaneously.