TF: Modularization Roadmap

tf-modularization-roadmap Doc

architecture terraform roadmap

Terraform Modularization Roadmap

Why Modularize

  • Blast radius — Today tofu apply touches all 25 platform resources. A typo in MinIO config could accidentally recreate Harbor. Modules let you -target by module.
  • Readability — 828 lines in one file. New developers can't find anything.
  • Reuse — The namespace → helm → funnel pattern repeats 6 times. A module eliminates copy-paste.
  • Testing — Modules can be tested independently with tofu plan and mock inputs.
  • Parallel work — Two developers changing different modules don't conflict as much.

Our Insight: Don't Over-Module

The industry best practice of "module everything" leads to abstraction layers that slow you down. Our for_each in services.tf is better than a module for the service onboarding pattern — it's declarative, flat, and the tfvars file IS the interface. We should modularize where we have repeated structure (platform components) but NOT wrap the for_each pattern in a module.

Proposed Module Extraction (pal-e-platform)

Module: platform-component

Encapsulates the repeating pattern: namespace → helm_release → tailscale_funnel
Used by: Forgejo, Woodpecker, Harbor, MinIO. NOT monitoring (it has extra resources like configmaps and separate Loki chart).

Module: monitoring

Special case — kube-prometheus-stack + loki-stack + datasource configmap + grafana funnel

Module: minio

Special case — helm release + 2 funnels (console + API) + bucket/IAM management

Target File Tree (pal-e-platform)

pal-e-services: Keep Flat

The services.tf for_each pattern should NOT be modularized. It's already declarative and flat. The interface IS the tfvars map. A module would add a layer of indirection for no benefit. If anything, split main.tf into:

Migration Strategy

  • Extract monitoring module first — most complex, highest value
  • Use moved blocks — avoids destroy/recreate. moved { from = helm_release.forgejo; to = module.forgejo.helm_release.this }
  • One module per PR — keep blast radius small
  • Validate with tofu plan — must show 0 changes after migration

When To Do This

Modularization is a prerequisite for environments (same modules, different vars). Do it before the environment split, after the CI pipeline is in place (so you can validate the refactor in CI).