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
-targetadalah 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 jalankanterraform plantanpa 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=INFOuntuk melihat API call mana yang paling banyak memakan waktu sebelum memutuskan cara optimasi.-refresh=falseadalah 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 initdari 30-60 detik menjadi 2-5 detik — wajib ada di CI/CD yang sering dijalankan.-targetuntuk 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 →