Skip to content
harry-suryapambagya
Back to blog

Terraform modules yang benar-benar reusable

Pelajaran dari tiga tahun bikin Terraform modules yang salah — dan pattern yang akhirnya stick.

2 min read
On this page3 sections

Ada satu kebenaran yang bikin aku males nulis soal Terraform: 80% “best practice” yang kamu temukan di blog pertama kali, baru akan kelihatan salah setelah kamu jalanin di production selama enam bulan.

Post ini bukan best practice. Ini cuma “pattern yang akhirnya aku pakai” setelah beberapa kali refactor.

Masalahnya: module yang terlalu pintar

Module pertama yang aku bikin selalu bentuknya begini:

module "vpc" {
source = "./modules/vpc"
name = "production"
environment = "prod"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b", "us-east-1c"]
enable_nat = true
enable_vpn = false
enable_flow_logs = true
tags = {
Project = "main"
}
}

Kelihatan rapi. Tapi begitu kebutuhan mulai nyeleneh — misalnya “VPC ini butuh 2 NAT tapi cuma untuk private subnet tertentu” — module-nya mulai bloated jadi seperti ini:

enable_nat = true
nat_gateway_count = 2
nat_gateway_subnets = ["private-a", "private-b"]
nat_gateway_eip_allocation = "managed"

Setiap edge case jadi variable baru. 6 bulan kemudian, file variables.tf punya 80 variables.

Yang akhirnya aku pakai: module kecil + composition

Alih-alih satu module besar yang mencoba handle semua kasus, aku pecah jadi building blocks yang lebih primitif:

module "vpc" {
source = "./modules/vpc-network"
cidr = "10.0.0.0/16"
azs = var.azs
}
module "public_subnets" {
source = "./modules/subnets"
vpc_id = module.vpc.id
cidrs = ["10.0.0.0/20", "10.0.16.0/20"]
public = true
}
module "nat" {
source = "./modules/nat-gateway"
subnet_id = module.public_subnets.ids[0]
}

Lebih verbose. Tapi:

  • Setiap module punya satu tanggung jawab.
  • Edge case tidak lagi jadi variable — kamu compose ulang dari building block.
  • Testing lebih mudah karena scope kecil.

Aturan praktis yang aku pegang

  1. Module = abstraksi, bukan preset. Kalau isinya cuma count = var.enable_x ? 1 : 0, mungkin itu resource biasa aja.
  2. Variable > 10 = smell. Waktu module punya lebih dari 10 variables, 90% kemungkinan dia sudah mencoba handle dua use case berbeda.
  3. Output yang kamu butuhkan hari ini, bukan yang mungkin dibutuhkan besok. YAGNI berlaku di sini juga.
  4. Versioning itu wajib. Begitu module dipakai di > 1 tempat, tag dia. source = "git::...?ref=v1.2.3".

Belum sempurna, tapi paling nggak terraform plan tidak lagi jadi lotere.