Belajar k6 - Konfigurasi Load Test dan Environment Variables
Series/Belajar k6/Episode 7
Episode 7 of 19

Belajar k6 - Konfigurasi Load Test dan Environment Variables

Merancang konfigurasi load test yang matang: stages ramping, threshold lanjutan, area ext, dan environment variables lewat __ENV agar skrip yang sama berjalan berbeda untuk lingkungan local, staging, dan menyerupai produksi.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Pendahuluan

Di episode 6 kalian merapikan skrip menjadi modul-modul yang bisa dipakai ulang — helper request, modul auth, dan buildOptions() yang menyatukan threshold. Namun ada satu kenyataan yang belum kita hadapi: angka-angka seperti vus: 10 dan duration: "30s" masih membeku di dalam kode. Skrip yang sama dipakai untuk local, staging, dan lingkungan menyerupai produksi — padahal kebutuhannya sangat berbeda.

Episode ini menjawab pertanyaan yang menentukan kualitas load test skala tim: bagaimana mengonfigurasi test tanpa mengubah kode? Kita akan membedah opsi-opsi canggih — stages (ramping), thresholds lanjutan, dan area ext — lalu menghubungkannya dengan environment variables lewat __ENV. Di akhir episode, satu skrip k6 yang sama bisa berjalan sebagai smoke test di laptop, load test penuh di staging, dan soak singkat di lingkungan produksi — hanya dengan berpindah perintah, bukan berpindah file.

Kenapa Konfigurasi Harus Hidup di Luar Kode

Bayangkan mengubah beban test setiap kali ingin mencoba skenario baru: buka file, edit vus, simpan, jalankan, ulangi. Dua masalah muncul. Pertama, kode dan konfigurasi tercampur — perubahan "berapa beban" jadi satu dengan perubahan "bagaimana skrip bekerja", menyulitkan review dan memicu kesalahan. Kedua, satu lingkungan tidak cocok untuk semua — beban 200 VU yang wajar untuk staging adalah serangan brutal untuk laptop pengembang.

Prinsipnya sederhana: skrip adalah kode, beban dan lingkungan adalah konfigurasi. Skrip ditulis sekali, dikelola di version control; beban dan target URL disuntikkan saat eksekusi. Inilah yang membuka pintu ke CI/CD yang kita bahas di episode 16 nanti.

Stages: Beban yang Berubah Seiring Waktu

vus dan duration menghasilkan beban yang konstan — 20 pengguna menekan server dengan ritme yang sama selama 30 detik. Beban seperti itu jarang terjadi di dunia nyata. Pengguna datang bertahap, ramai di jam tertentu, lalu pergi. stages merekam rencana itu sebagai daftar langkah:

Stages: ramp up, stabil, lalu turun
export const options = {
  stages: [
    { duration: "1m", target: 20 },
    { duration: "2m", target: 50 },
    { duration: "3m", target: 50 },
    { duration: "1m", target: 0 },
  ],
};

Setiap langkah menyatakan: dalam duration ini, naikkan (atau turunkan) jumlah VU hingga mencapai target. Di atas, beban naik dari 0 ke 20 di menit pertama, merangkak ke 50 di dua menit berikutnya, stabil lima menit, lalu melandai kembali ke nol. Bentuk ini disebut ramping — dan ia menjawab pertanyaan yang tidak bisa dijawab beban konstan: pada titik berapa server mulai menyerah?

Ramping juga melindungi server dari cold start yang tidak realistis. Bayangkan menguji cache yang masih kosong: 500 VU tiba-tiba menyerbu cache dingin akan melaporkan latensi tinggi yang salah. Dengan ramp up, cache sempat terisi dan pengukuran mencerminkan kondisi operasional, bukan kondisi awal.

Perlu diingat dari episode 2: stages tidak bisa digabung dengan vus dan duration dalam satu skrip — k6 menolak kombinasi ini. Pilih salah satu model.

Threshold Lanjutan: Menegakkan Standar yang Lebih Ketat

Episode 4 memperkenalkan threshold dasar berbentuk string. Untuk kebutuhan produksi, threshold bisa berupa array dengan beberapa aturan dan mode abortOnFail — hentikan test segera ketika ambang dilanggar, alih-alih menunggu selesai:

Threshold lanjutan: multi-aturan dan abort
export const options = {
  thresholds: {
    http_req_duration: [
      { threshold: "p(95)<500", abortOnFail: true },
      "p(99)<1000",
    ],
    http_req_failed: ["rate<0.01"],
  },
};

Membaca ini: 95% request harus selesai di bawah 500 ms dan bila dilanggar test berhenti segera (abortOnFail); 99% request di bawah 1000 ms; dan rasio request gagal di bawah 1%. abortOnFail sangat berharga di CI — alih-alih membuang waktu menjalankan beban 10 menit yang jelas-jelas sudah melewati ambang, pipeline gagal di menit ketiga dan tim bisa menginvestigasi lebih cepat.

Kombinasikan dengan gracefulStop untuk memberi waktu jeda, dan catat bahwa setiap threshold yang dilanggar membuat k6 keluar dengan exit code 99 — bahasa sukses-gagal yang dipahami semua pipeline.

Area ext: Konfigurasi untuk Tool Pihak Ketiga

Opsi ext adalah ruang cadangan di options untuk tool dan ekstensi pihak ketiga menaruh konfigurasinya. Contoh klasik adalah runner k6 Cloud yang membaca identitas project dan nama test dari sana:

Area ext untuk konfigurasi pihak ketiga
export const options = {
  vus: 10,
  duration: "30s",
  ext: {
    loadimpact: {
      projectID: 12345,
      name: "belajar-k6-staging",
    },
  },
};

ext tidak mengubah perilaku eksekusi lokal sama sekali — ia hanya dibaca oleh layanan atau ekstensi yang memahami strukturnya. Gunakan area ini hanya untuk keperluan yang memang spesifik pihak ketiga; konfigurasi yang kalian kendalikan sendiri lebih tepat diletakkan di skrip atau __ENV. (Perlu dicatat: untuk Grafana Cloud, alur modern lebih sering memakai flag CLI k6 cloud run daripada menaruh konfigurasi di ext.)

Environment Variables: Parameter Tanpa Menyentuh Kode

Inilah pahlawan episode ini. k6 membuka akses ke environment variables lewat objek global __ENV — nilainya bisa disuntikkan saat menjalankan test dengan flag -e:

Membaca __ENV dengan nilai default
const BASE_URL = __ENV.BASE_URL || "https://api.example.com";
const VUS = Number(__ENV.VUS) || 10;
 
export const options = {
  vus: VUS,
  duration: __ENV.DURATION || "30s",
};

Lalu jalankan dengan parameter runtime:

Menjalankan test dengan -e
k6 run -e BASE_URL=https://staging.example.com -e VUS=50 -e DURATION=5m script.js

Dua hal yang wajib diingat tentang __ENV:

  • Semua nilai __ENV adalah string. Beban numerik wajib diubah dengan Number(__ENV.VUS) — jika tidak, vus bernilai string dan k6 menolak dengan error.
  • Nilai default di belakang || memastikan skrip tetap bisa dijalankan tanpa argumen apa pun. Skrip yang aman adalah skrip yang bisa dijalankan polos dan bisa diparameterisasi.

Ingat pola buildOptions dari episode 6? Sekarang kekuatannya terasa. buildOptions bisa membaca __ENV, sehingga satu fungsi menghasilkan varian options yang berbeda per lingkungan.

Profil Lingkungan: Local, Staging, dan Produksi

Praktik terbaik yang menyatukan semuanya: definisikan profil lingkungan dalam satu modul konfigurasi, dan pilih profil lewat __ENV.ENV:

config.js — profil per lingkungan
const profiles = {
  local: { baseUrl: "http://localhost:3000", vus: 5, duration: "1m" },
  staging: { baseUrl: "https://staging.example.com", vus: 50, duration: "5m" },
  production: { baseUrl: "https://api.example.com", vus: 200, duration: "10m" },
};
 
export function currentProfile() {
  return profiles[__ENV.ENV] || profiles.local;
}

Dan main.js tinggal membaca profil itu:

main.js — memakai profil aktif
import { currentProfile } from "./config.js";
 
const profile = currentProfile();
 
export const options = {
  vus: profile.vus,
  duration: profile.duration,
  thresholds: {
    http_req_duration: ["p(95)<500"],
  },
};
 
export default function () {
  console.log(`Menguji ${profile.baseUrl} dengan ${profile.vus} VU`);
}

Menjalankan test untuk tiap lingkungan kini tinggal satu baris — dan tidak ada satu pun nilai lingkungan yang bocor ke dalam kode:

Satu skrip, tiga lingkungan
k6 run -e ENV=local script.js
k6 run -e ENV=staging script.js
k6 run -e ENV=production script.js

Perhatikan bahwa skrip yang sama berjalan di ketiga lingkungan. Ini bukan sekadar kenyamanan — ini konsistensi: test yang kalian jalankan di laptop adalah test yang sama yang dijalankan di pipeline. Perbedaannya hanya konfigurasi.

Important

Saat memilih profil produksi, dua pertimbangan wajib ada: izin dan threshold. Pastikan load test terhadap lingkungan produksi dijadwalkan dengan persetujuan pemilik layanan, dan threshold untuk lingkungan lambat tidak disalin mentah dari staging — profil produksi yang menyalin threshold staging hanya akan memproduksi false alarm.

Kesalahan Umum

  1. Melupakan Number() pada __ENV numerik. Semua env var adalah string; vus dan nilai metrik yang lolos sebagai string akan membuat k6 menolak atau menghitung salah.
  2. Menggabungkan stages dengan vus dan duration. k6 menolak kombinasi ini. Pilih salah satu model beban.
  3. Menghardcode URL lingkungan di skenario. Itu membuat skrip hanya berjalan di satu lingkungan — menghancurkan nilai portabilitasnya.
  4. Menyalin threshold antar lingkungan tanpa berpikir. Lingkungan yang lebih lambat (local, VM kecil) membutuhkan ambang yang lebih realistis.
  5. Menyimpan rahasia di -e untuk test produksi. Token dan kredensial tetap rahasia — injeksikan lewat secret manager di CI, bukan hardcode di perintah.

Penutup

Di episode 7 ini kalian telah mengubah skrip k6 dari program menjadi alat:

  • Stages ramping: beban yang naik, stabil, dan turun — merekam titik patah server dengan akurat.
  • Threshold lanjutan: array multi-aturan, abortOnFail untuk kegagalan cepat, dan exit code 99 untuk pipeline.
  • Area ext: ruang konfigurasi khusus tool pihak ketiga.
  • __ENV: parameter runtime lewat -e, dengan default yang aman.
  • Profil lingkungan: satu skrip, banyak lingkungan — local, staging, dan menyerupai produksi.

Jalankan skrip profil ini dengan k6 run -e ENV=staging main.js dan bandingkan hasilnya dengan versi local. Sekarang skrip kalian bisa dijalankan di lingkungan mana pun — tapi ada satu hal yang masih membuatnya kurang realistis: data yang dipakai masih hardcode di dalam skrip. Di episode 8 kita membuka data — Data Driven Testing dan Ketersediaan Data: membaca data dari CSV dan JSON, merandomisasi input dengan randomItem, dan menjaga kebersihan data agar test tetap bisa diulang. Sampai jumpa di episode 8!