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.
flowchart TD
A["terraform plan"] --> B["Refresh state\n(API calls)"]
B --> C["Compare with\nconfig"]
C --> D["Generate plan"]
B --> E["100 resources\n= 100+ API calls"]
E --> F["Slow plan\n~20 min"]
style A fill:#3b82f6,stroke:#1e40af,color:#fff
style B fill:#f59e0b,stroke:#d97706,color:#fff
style C fill:#8b5cf6,stroke:#6d28d9,color:#fff
style D fill:#10b981,stroke:#059669,color:#fff
style E fill:#ef4444,stroke:#dc2626,color:#fff
style F fill:#ef4444,stroke:#dc2626,color:#fffMengukur 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
flowchart LR
A["Split\nstate"] --> B["-target\nspecific"]
B --> C["Parallel\nexecution"]
C --> D["Caching\nprovider"]
D --> E["Fast plan\n~2 min"]
style A fill:#3b82f6,stroke:#1e40af,color:#fff
style B fill:#3b82f6,stroke:#1e40af,color:#fff
style C fill:#8b5cf6,stroke:#6d28d9,color:#fff
style D fill:#8b5cf6,stroke:#6d28d9,color:#fff
style E fill:#10b981,stroke:#059669,color:#fffParallelism Tuning #
Terraform bisa membuat resource secara paralel. Mengatur parallelism bisa mempercepat apply.
# Default: 10 resource paralel
terraform apply
# Naikkan untuk infrastruktur besar
terraform apply -parallelism=20
# Turunkan jika API rate-limited
terraform apply -parallelism=3
# Untuk provider yang sensitif terhadap concurrent request
# (misalnya: beberapa SaaS API)
terraform apply -parallelism=1
# Monitoring waktu eksekusi
time terraform plan
time terraform apply -auto-approve
# Terraform trace logging untuk debugging performa
TF_LOG=TRACE terraform plan 2>&1 | tee trace.log
# Cari "applyable" untuk melihat resource mana yang lambat
Provider Caching #
# Enable provider plugin caching untuk percepat init
# ~/.terraformrc:
# provider_cache {
# dir = "$HOME/.terraform.d/plugin-cache"
# }
# Atau set via environment variable
export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache"
terraform init
# Provider hanya di-download sekali, workspace lain pakai cache
# Bersihkan cache jika perlu
rm -rf $TF_PLUGIN_CACHE_DIR/*
# Gunakan data source yang efisien
# BURUK: Mengambil semua instance
data "aws_instances" "all" {}
# BAIK: Filter spesifik
data "aws_instances" "web" {
filter {
name = "tag:Role"
values = ["web"]
}
}
Plan Caching #
# Terraform tidak cache plan secara native
# Tapi ada beberapa strategi untuk percepat:
# 1. Simpan plan output dan apply nanti
terraform plan -out=plan.cache
terraform apply plan.cache
# Menghindari re-plan yang bisa memakan waktu
# 2. Targeted refresh (hanya resource yang berubah)
terraform plan -target=aws_instance.web
# Berguna saat development, JANGAN di production
# 3. Reduce data source calls
# Kurangi jumlah data source, gunakan locals caching
# 4. Parallel backend initialization
# Terraform init bisa mendownload provider secara parallel
terraform init -plugin-dir=/shared/plugin-cache
Provider Plugin Caching #
# Cache provider plugins untuk percepat init
mkdir -p ~/.terraform.d/plugin-cache
# ~/.terraformrc
# plugin_cache_dir = "$HOME/.terraform.d/plugin-cache"
# Atau set via environment variable
export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache"
# Di CI/CD: persist cache antara runs
# GitHub Actions:
- uses: actions/cache@v3
with:
path: ~/.terraform.d/plugin-cache
key: terraform-providers-${{ hashFiles('.terraform.lock.hcl') }}
# Shared plugin cache untuk team
# Simpan di shared filesystem atau S3
terraform init -plugin-dir=/shared/terraform/plugins
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 →