Performance Optimization #

Terraform yang lambat bukan hanya masalah kenyamanan — pipeline CI/CD yang menunggu 20 menit untuk satu plan akan memperlambat seluruh alur kerja tim. Sebagian besar masalah performa Terraform berasal dari satu sumber: terlalu banyak API call ke cloud provider saat refresh state. Memahami di mana waktu habis dan cara menguranginya — tanpa mengorbankan keandalan — adalah keterampilan penting untuk tim yang mengelola infrastruktur besar.

Mengukur Waktu Sebelum Optimasi #

# Selalu ukur sebelum optimasi — jangan asumsi di mana bottleneck-nya

# Aktifkan logging detail
TF_LOG=INFO terraform plan 2>&1 | grep -E "provider|Refreshing|Reading"

# Atau gunakan timestamp untuk setiap fase
time terraform init
time terraform plan
time terraform apply

# Untuk profiling yang lebih detail (Terraform 1.2+)
TF_LOG=TRACE terraform plan 2>&1 | grep "provider.aws" | tail -50
# Ini menampilkan semua API call ke AWS provider

# Output yang perlu diperhatikan:
# [INFO] provider.aws: Refreshing state... (aws_instance.web)
# → Setiap baris ini adalah satu API call
# → Jika ada ratusan baris, ini sumber lambatnya

-refresh=false: Lewati Refresh State #

# ANTI-PATTERN: Selalu refresh (default)
terraform plan
# → Terraform memanggil API cloud untuk setiap resource di state
# → 200 resource = 200 API call sebelum plan mulai
# → Bisa memakan waktu menit jika banyak resource

# BENAR: Skip refresh jika state sudah diketahui akurat
terraform plan -refresh=false
# → Langsung bandingkan konfigurasi dengan state yang ada
# → Jauh lebih cepat, tapi tidak mendeteksi drift

# Kapan -refresh=false AMAN digunakan:
# ✓ Pipeline CI/CD di mana tidak ada yang bisa ubah infrastruktur di luar Terraform
# ✓ Saat iterasi cepat saat develop konfigurasi baru
# ✓ Setelah apply baru saja dijalankan (state pasti akurat)

# Kapan -refresh=false TIDAK AMAN:
# ✗ Jika ada kemungkinan perubahan manual di cloud
# ✗ Untuk drift detection (justru butuh refresh)
# ✗ Sebelum apply ke production yang sudah lama tidak di-plan

Parallelism: Kontrol Concurrency #

Terraform secara default menjalankan maksimal 10 operasi secara bersamaan. Untuk resource yang independen, meningkatkan angka ini bisa mempercepat apply. Tapi terlalu tinggi bisa menyebabkan API throttling dari cloud provider.

# Default parallelism adalah 10
terraform apply

# Naikkan untuk infrastruktur dengan banyak resource independen
terraform apply -parallelism=20

# Turunkan jika sering kena API rate limit
terraform apply -parallelism=5

# Untuk AWS: rate limit berbeda per service
# EC2: cukup tinggi (bisa parallelism 20+)
# IAM: lebih ketat (tetap di 5-10)
# CloudFormation: sangat ketat (turun ke 3-5)

# Temukan nilai optimal dengan eksperimen:
for p in 5 10 15 20; do
  echo "Testing parallelism=$p"
  time terraform apply -parallelism=$p -auto-approve
done

Optimasi Data Source #

Data source yang tidak perlu adalah salah satu penyebab tersembunyi plan yang lambat — setiap data source menghasilkan setidaknya satu API call.

# ANTI-PATTERN: Data source yang dipanggil terlalu sering
# Setiap resource memanggil data source sendiri-sendiri
resource "aws_instance" "web_1" {
  ami = data.aws_ami.ubuntu.id  # 1 API call
}
resource "aws_instance" "web_2" {
  ami = data.aws_ami.ubuntu.id  # API call yang sama lagi (tapi Terraform cache-nya)
}
# Terraform otomatis cache data source yang sama — ini sebenarnya OK

# Yang BENAR-BENAR bermasalah: data source dengan filter yang berat
data "aws_instances" "all_running" {
  filter {
    name   = "instance-state-name"
    values = ["running"]
  }
  # Ini list SEMUA running instance → mahal jika ada ribuan instance
}

# BENAR: Gunakan filter yang lebih spesifik
data "aws_instances" "web_fleet" {
  filter {
    name   = "tag:Role"
    values = ["web-server"]
  }
  filter {
    name   = "tag:Environment"
    values = ["production"]
  }
  # Filter ketat → API call lebih ringan
}
# ANTI-PATTERN: Data source untuk nilai yang sudah diketahui
data "aws_region" "current" {}
data "aws_caller_identity" "current" {}

# Jika region dan account ID sudah diketahui dan tidak berubah,
# lebih efisien menggunakan variable atau local
locals {
  region     = "ap-southeast-1"
  account_id = "123456789012"
}

# Data source tetap berguna untuk nilai yang memang dinamis
# (AMI terbaru, AZ yang available, dll.)

-target: Operasi Tertentu Saja #

-target memungkinkan kamu menjalankan plan atau apply hanya pada resource tertentu, mengabaikan yang lain.

# Hanya plan resource tertentu
terraform plan -target=aws_instance.web
terraform plan -target=module.database

# Hanya apply resource tertentu
terraform apply -target=aws_security_group.new_rule

# Berguna untuk:
# ✓ Debug — isolasi resource yang bermasalah
# ✓ Bootstrap — buat resource yang dibutuhkan sebelum yang lain
# ✓ Emergency fix — perbaiki satu resource tanpa risiko ke yang lain
-target adalah alat untuk situasi khusus, bukan workflow rutin. Penggunaan berulang bisa menyebabkan state tidak konsisten — dependency graph Terraform tidak dijalankan penuh, sehingga perubahan pada resource yang di-target mungkin tidak mempropagasi ke resource yang bergantung padanya. Setelah menggunakan -target, selalu jalankan terraform plan tanpa target untuk memastikan tidak ada yang tertinggal.

Provider Cache #

Setiap kali terraform init dijalankan, Terraform mendownload provider. Di CI/CD yang sering dijalankan, ini memakan waktu dan bandwidth.

# Setup provider cache (di CI/CD atau lokal)
export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache"
mkdir -p $TF_PLUGIN_CACHE_DIR

# Sekarang terraform init akan cek cache sebelum download
terraform init
# Jika provider sudah di cache → langsung gunakan, tidak download ulang

# Di GitHub Actions: cache provider dengan actions/cache
- name: Cache Terraform Plugins
  uses: actions/cache@v4
  with:
    path: ~/.terraform.d/plugin-cache
    key: ${{ runner.os }}-terraform-${{ hashFiles('**/.terraform.lock.hcl') }}
    restore-keys: |
      ${{ runner.os }}-terraform-

- name: Terraform Init
  run: terraform init
  env:
    TF_PLUGIN_CACHE_DIR: ~/.terraform.d/plugin-cache

Mengoptimalkan terraform init #

# ANTI-PATTERN: terraform init yang download ulang setiap saat
terraform init  # Selalu download dari registry

# BENAR: Gunakan -upgrade hanya saat memang perlu upgrade provider
terraform init          # Gunakan versi yang sudah di-lock
terraform init -upgrade # Hanya saat ingin upgrade ke versi terbaru

# Untuk CI/CD: skip backend init jika tidak perlu
terraform init -backend=false  # Untuk validate saja, tanpa akses state

# Waktu benchmark tipikal:
# terraform init tanpa cache:   30-60 detik (download provider)
# terraform init dengan cache:  2-5 detik (copy dari cache)
# Selisih ini signifikan jika pipeline berjalan puluhan kali sehari

Ringkasan #

  • Ukur dulu, optimasi kemudian — aktifkan TF_LOG=INFO untuk melihat API call mana yang paling banyak memakan waktu sebelum memutuskan cara optimasi.
  • -refresh=false adalah optimasi terbesar untuk CI/CD yang dikontrol ketat — melewati ratusan API call refresh bisa memotong waktu plan dari menit menjadi detik.
  • Parallelism bisa dinaikkan dari default 10 untuk infrastruktur besar, tapi turunkan jika sering kena API rate limit dari cloud provider.
  • Data source dengan filter longgar adalah bottleneck tersembunyi — filter seketat mungkin agar API response lebih kecil dan cepat.
  • Provider cache memotong waktu terraform init dari 30-60 detik menjadi 2-5 detik — wajib ada di CI/CD yang sering dijalankan.
  • -target untuk situasi khusus saja — setelah digunakan, selalu jalankan plan penuh untuk memastikan tidak ada inconsistency yang tertinggal.

← Sebelumnya: Scale Terraform   Berikutnya: Anti-Pattern: Terraform as CM →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact