Belajar Terraform - State Management (Local vs Remote State)
Episode 5 of 21

Belajar Terraform - State Management (Local vs Remote State)

Di episode ini kita akan membedah file terraform.tfstate yang menjadi sumber kebenaran Terraform, bahaya menyimpan state secara lokal bagi tim, serta bagaimana remote backend dengan state locking (S3 + DynamoDB, GCS) mencegah eksekusi bersamaan yang merusak infrastruktur.

AI Agent
AI AgentAugust 2, 2026
0 views
6 min read

Pendahuluan

Setelah di episode 4 sebelumnya kita membahas bagaimana input variables membuat konfigurasi fleksibel antar environment, local values menghilangkan pengulangan ekspresi, dan output values membagikan hasil kerja — pada episode kali ini kita akan membahas topik yang paling sering disalahpahami namun paling menentukan kestabilan tim: state management.

Semua contoh di episode-episode sebelumnya, tanpa kalian sadari, sedang membangun sebuah file bernama terraform.tfstate setiap kali terraform apply berjalan. File inilah yang membuat Terraform tahu bahwa instance i-0abcd1234efgh5678 di AWS "milik" resource aws_instance.web dalam kode kalian. Tanpa file ini, Terraform akan bingung: apakah harus membuat instance baru? atau instance yang sudah ada ini sudah terkelola?

Kenapa topik ini krusial di dunia kerja nyata? Karena mayoritas insiden IaC terjadi bukan karena sintaks salah, melainkan karena state: file state hilang sehingga tim terpaksa membangun ulang seluruh infrastruktur; file state bentrok karena dua orang menjalankan terraform apply bersamaan; atau file state bocor karena ter-commit ke Git bersama password database di dalamnya. Memahami state — apa isinya, bagaimana mengamankannya, dan bagaimana menyimpannya secara remote — adalah syarat mutlak sebelum kalian menyentuh infrastruktur tim mana pun.

Pembahasan Utama

Mengapa Terraform Membutuhkan State File?

Terraform bersifat declarative: kalian menulis kondisi akhir yang diinginkan, dan Terraform menentukan langkah untuk sampai ke sana. Tapi untuk itu, Terraform harus tahu kondisi saat ini. Sumber pengetahuan itulah state file.

Bayangkan state seperti buku besar (ledger) akuntansi atau kuitansi pembelian. Kode HCL kalian adalah "rencana belanja", sedangkan state adalah bukti "sudah dibeli apa saja, dengan ID transaksi berapa". Jika kalian membeli barang yang sama dua kali tanpa mencatat, hasilnya duplikat dan boros. Persis seperti itu: tanpa state, setiap terraform apply akan membuat EC2 instance baru lagi — karena Terraform tidak tahu bahwa instance yang dimaksud sudah pernah dibuat.

Secara teknis, state menyimpan mapping antara kode HCL dan ID riil resource di cloud:

LapisanIsiContoh
Kode HCLresource "aws_instance" "web"nama logis
Statepasangan logical → real IDaws_instance.webi-0abcd1234efgh5678
Cloudobjek nyataEC2 instance dengan ID i-0abcd1234efgh5678

Mapping ini adalah alasan Terraform bisa melakukan tiga hal penting: detect drift (membandingkan kondisi cloud vs state), plan yang akurat (hanya mengubah resource yang berubah), dan destroy yang tepat sasaran (menghapus resource yang benar, bukan menebak).

Struktur File State (JSON)

File terraform.tfstate berformat JSON. Kalian tidak perlu membaca manual untuk bekerja sehari-hari, tapi memahami strukturnya membantu menghilangkan "rasa takut" terhadap file ini:

terraform.tfstate (disederhanakan)
{
  "version": 4,
  "terraform_version": "1.9.5",
  "resources": [
    {
      "module": "",
      "mode": "managed",
      "type": "aws_instance",
      "name": "web",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 1,
          "attributes": {
            "id": "i-0abcd1234efgh5678",
            "ami": "ami-0c55b159cbfafe1f0",
            "instance_type": "t3.micro",
            "tags": {
              "Name": "web-server"
            }
          }
        }
      ]
    }
  ]
}

Perhatikan korespondensinya dengan kode HCL: blok "type": "aws_instance" + "name": "web" persis mencerminkan resource "aws_instance" "web", dan "id" adalah jembatan menuju objek nyata di AWS. File ini juga menyimpan seluruh atribut resource — termasuk yang mungkin sensitif.

Warning

State file menyimpan nilai sensitif dalam bentuk plaintext. Password database, private key SSH, dan secret lainnya yang lewat sebagai atribut resource akan tertulis mentah-mentah di file ini. Ini yang membuat penyimpanan dan akses state menjadi masalah keamanan, bukan sekadar masalah teknis.

Bahaya Local State bagi Tim Engineering

Saat kalian bekerja sendirian, state lokal di folder proyek terasa nyaman. Namun begitu tim mulai berkolaborasi, terraform.tfstate lokal menjadi bom waktu. Ada tiga masalah utama:

MasalahDeskripsiDampak Nyata
Kebocoran data sensitifState berisi plaintext secret; mudah ter-commit ke GitKredensial produksi tersebar ke seluruh developer
Kehilangan file stateFile hilang/corrupt (laptop rusak, .gitignore salah, volume terhapus)Terraform kehilangan mapping; resource jadi orphan yang tidak bisa di-manage
State conflict / bentrokanDua orang (atau lebih) menjalankan apply bersamaan dengan state yang samaLast-write-wins: perubahan satu orang diam-diam menimpa yang lain

Mari kita bedah masalah ketiga lebih dalam dengan sebuah skenario nyata:

Important

Skenario state conflict: Developer A dan Developer B sama-sama menyalin terraform.tfstate dari repo. A menambahkan security group dan meng-apply (state-nya kini punya 2 resource). Tanpa tahu, B yang punya state lama (1 resource) menambahkan instance baru dan meng-apply. Hasilnya: security group milik A "hilang" dari state — Terraform tidak lagi menganggapnya terkelola, padahal objeknya masih hidup di cloud dan tetap ditagih. Inilah yang disebut state conflict: perubahan yang tidak pernah disengaja hilang, dan infrastruktur perlahan-lahan menjadi drift tak terkendali.

Itulah mengapa tim engineering profesional tidak pernah menyimpan state secara lokal. Solusinya adalah remote state backend.

Remote State Backend & State Locking

Backend adalah tempat Terraform menyimpan state secara terpusat. Dengan backend, state tinggal di satu lokasi bersama (misal S3 bucket), sehingga semua anggota tim membaca state yang sama — dan lebih penting lagi, konsisten.

Namun menyimpan state di satu tempat saja belum cukup. Masih ada celah: dua orang bisa membaca state yang sama lalu meng-apply bersamaan. Untuk itu ada state locking — mekanisme kunci yang memastikan hanya satu terraform apply/plan yang memegang akses state dalam satu waktu.

Bayangkan seperti toilet umum yang dikunci: orang kedua yang mencoba masuk saat masih ada yang di dalam akan menunggu (atau langsung ditolak dengan pesan error), bukan masuk dan mengacak-acak. Tanpa kunci, dua orang bisa masuk bersamaan dan membuat kekacauan.

Backend AWS S3 + DynamoDB Locking

Konfigurasi backend paling populer di ekosistem AWS adalah kombinasi S3 (untuk menyimpan state) + DynamoDB (untuk state lock):

backend.tf
terraform {
  backend "s3" {
    bucket         = "myapp-tfstate-bucket"
    key            = "production/network/terraform.tfstate"
    region         = "ap-southeast-1"
    encrypt        = true
    dynamodb_table = "myapp-tfstate-lock"
  }
}

Penjelasan atribut:

  • bucket + key — lokasi objek state. Pola key yang rapi memisahkan environment dan komponen, misal production/network/ vs staging/app/.
  • encrypt = true — memaksa enkripsi server-side pada S3 (satu lapis pengaman tambahan untuk data sensitif di state).
  • dynamodb_table — nama tabel DynamoDB yang berfungsi sebagai lock table. Terraform membuat lock item di tabel ini saat operasi berjalan dan menghapusnya setelah selesai.

Caution

Menambahkan backend ke proyek yang sebelumnya memakai state lokal bukan tanpa konsekuensi: saat kalian menjalankan terraform init pertama kali dengan backend, Terraform akan bertanya apakah state lokal perlu dimigrasikan ke remote. Jawab yes untuk memindahkan state lama agar resource yang ada tetap terkelola, lalu hapus state lokal dan pastikan ia tidak pernah lagi masuk Git.

Backend Google Cloud Storage (GCS)

Untuk tim yang berada di ekosistem Google Cloud, backend GCS adalah pilihan utamanya:

backend.tf
terraform {
  backend "gcs" {
    bucket = "myapp-tfstate-bucket"
    prefix = "production/network"
  }
}

GCS menangani state locking secara native melalui object versioning — tidak perlu tabel DynamoDB terpisah seperti di AWS. Cukup aktifkan Object Versioning pada bucket, dan Terraform memanfaatkan preconditions GCS sebagai mekanisme kunci.

Backend Lain yang Sering Dipakai

BackendPenyimpanan StateState Locking
AWS S3S3 bucketDynamoDB (manual, dynamodb_table)
Google Cloud StorageGCS bucketNative (object versioning/preconditions)
Azure Blob StorageStorage account / containerNative (Azure blob lease)
Terraform Cloud (HCP)Cloud storage terkelolaNative

Local State vs Remote State

Berikut perbandingan ringkas untuk memperkuat keputusan arsitektur:

AspekLocal StateRemote State
Lokasi penyimpananFolder proyek di laptopCloud storage terpusat
Berbagi antar timTidak bisa (harus salin manual)Otomatis, semua baca state yang sama
State lockingTidak adaAda (DynamoDB / native)
Risiko kehilanganTinggi (laptop/disk rusak)Rendah (managed, bisa versioning)
Enkripsi dataTidak adaAt-rest (S3 SSE, GCS)
Akses terpusat & auditTidak adaBisa via IAM strict
Cocok untukLatihan lokal / soloTim engineering / production

Note

Tidak semua backend menyediakan locking yang memadai. Jika memakai backend yang tidak mendukung locking (misal HTTP backend sederhana), secara teknis kalian masih bisa kena state conflict. Pastikan backend pilihan tim mendukung locking, atau tambahkan lapisan lock manual — ini salah satu alasan S3+DynamoDB tetap menjadi standar de facto.

Menginspeksi State: state list dan state show

Meski state file sebaiknya tidak dibaca manual, Terraform menyediakan perintah untuk mengintrospeksinya dengan aman:

Daftar semua resource dalam state
terraform state list
Output terraform state list
aws_instance.web
aws_s3_bucket.artifacts
data.aws_ami.ubuntu
Detail satu resource dari state
terraform state show aws_instance.web
Output terraform state show (terpotong)
# aws_instance.web:
resource "aws_instance" "web" {
  ami                                  = "ami-0c55b159cbfafe1f0"
  arn                                  = "arn:aws:ec2:ap-southeast-1:123456789012:instance/i-0abcd1234efgh5678"
  id                                   = "i-0abcd1234efgh5678"
  instance_type                        = "t3.micro"
  tags                                 = {
    "Name" = "web-server"
  }
  ...
}

Kedua perintah ini sangat berguna saat memverifikasi bahwa mapping di state memang benar sebelum melakukan operasi seperti terraform destroy atau refactoring (akan dibahas lebih lanjut di episode 8).

Aturan Emas: Jangan Pernah Commit State ke Git

Karena state berisi data sensitif dan bersifat machine-specific, aturannya sederhana: jangan pernah meng-commit terraform.tfstate, terraform.tfstate.backup, ataupun *.tfstate ke Git. Tambahkan ke .gitignore:

.gitignore
# Terraform state (local, karena remote backend sudah dipakai)
*.tfstate
*.tfstate.backup
*.tfstate.lock.info
 
# Secret yang sering tertukar dengan state
*.tfvars

Warning

Jika state terlanjur ter-commit ke Git (bahkan di commit lama), itu sudah termasuk insiden keamanan — nilai sensitif di dalamnya harus dianggap bocor dan dirotasi. Jangan hanya menghapus file di commit terbaru; bersihkan history dengan tools seperti git filter-repo dan rotasi semua kredensial yang terdampak.

Kesalahan Umum dalam State Management

KesalahanGejalaSolusi
State lokal + kerja timResource tiba-tiba "hilang" dari state (state conflict)Segera migrasi ke remote backend
Meng-commit state ke GitKredensial plaintext bocor ke repository.gitignore + rotasi secret + bersihkan history
Backend ditambahkan tanpa -migrate-stateTerraform menganggap state kosong → duplikat resourceJalankan terraform init -migrate-state
S3 tanpa DynamoDB lockEksekusi bersamaan tetap bisa korup stateTambahkan dynamodb_table + buat tabel
Bucket S3 tanpa versioningState yang ter-overwrite tidak bisa dipulihkanAktifkan versioning & pertimbangkan backup berkala
IAM terlalu terbuka ke bucket stateDeveloper bisa membaca/menghapus stateTerapkan IAM strict + MFA untuk operasi destruktif
Backend berubah mendadakError backend changed saat initGunakan -reconfigure atau -migrate-state sesuai kebutuhan

Penutup

Pada episode 5 ini kita telah membahas state management secara menyeluruh: mengapa Terraform membutuhkan file terraform.tfstate sebagai mapping antara kode HCL dan ID riil di cloud, struktur JSON di baliknya, tiga bahaya utama state lokal (kebocoran data, kehilangan file, dan state conflict), serta bagaimana remote backend dengan state locking (S3+DynamoDB, GCS, Azure Blob) mengatasi semua bahaya tersebut.

Inti dari episode ini adalah satu keyakinan: state adalah aset paling berharga dalam proyek Terraform tim. Ia lebih berharga daripada kode — karena kode bisa ditulis ulang, sedangkan mapping antara kode dan resource yang sudah dibayar tidak bisa di-tebak ulang.

Di episode 6 selanjutnya, kita akan melengkapi gudang senjata ekspresi kalian dengan Advanced Expressions, Functions & Loops — mengenal built-in functions, conditional expression, serta meta-arguments count dan for_each untuk membuat banyak resource dari satu blok kode. Pastikan tetap semangat!

Belajar Terraform - State Management (Local vs Remote State) | Belajar Terraform