Sempurnakan perilaku autoscaling: pollingInterval dan cooldownPeriod yang optimal, kalkulasi saturation replica per pesan, menghadapi throttling API provider, serta benchmark latency scale-up dan trade-off biaya versus responsivitas.

Di episode 18 kita belajar mendiagnosa KEDA saat gagal. Sekarang waktunya menggeser fokus: dari berfungsi menjadi berfungsi optimal. Dua ScaledObject identik bisa memiliki latency scale-up yang berbeda 3 kali lipat hanya karena pollingInterval. Episode ini membahas Performance & Tuning: parameter yang harus di-tuning, cara menghitung replica yang pas dengan beban, menghindari throttling provider, dan metodologi benchmark sehingga keputusan tuning didasarkan data, bukan tebakan.
Dua parameter paling berpengaruh:
pollingInterval — seberapa sering KEDA mengecek nilai metrik. Default 30 detik. Lebih kecil (10-15 detik) = reaksi lebih cepat, tapi lebih banyak request ke provider.cooldownPeriod — berapa lama KEDA menunggu tanpa event sebelum menurunkan replika. Default 300 detik. Lebih besar = workload naik turun lebih tenang, tapi replika idle lebih lama.Aturan praktis:
| Workload | pollingInterval | cooldownPeriod | Alasan |
|---|---|---|---|
| Batch / antrean besar | 15-30 | 180-300 | Throughput tinggi, toleran delay |
| API interaktif (HTTP Add-on) | 10-15 | 120-180 | Responsif, cold start pendek |
| Data pipeline streaming | 5-10 | 60-120 | Latensi rendah, event kontinu |
| Cost-sensitive / jarang | 30-60 | 300-600 | Minimalkan replika idle |
Tip
Semakin kecil pollingInterval, semakin mahal permintaan ke provider queue (SQS, Azure Service Bus) — dan ini bisa menabrak throttling API. Sesuaikan dengan kuota provider, bukan hanya kebutuhan latensi.
Satu replika memproses berapa pesan sebelum jenuh? Angka ini menentukan queueLength (threshold per replika). Ukur lewat observasi: amati throughput tiap replica pada metrik keda_scaler_metrics_value, lalu cari titik di mana penambahan replica tidak lagi menaikkan throughput total.
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: order-worker
namespace: orders
spec:
scaleTargetRef:
name: order-worker
pollingInterval: 15
cooldownPeriod: 180
minReplicaCount: 0
maxReplicaCount: 30
triggers:
- type: aws-sqs-queue
metadata:
queueURL: https://sqs.ap-southeast-1.amazonaws.com/1234/orders
queueLength: "25"
authenticationRef:
name: sqs-authLogika sederhana: queueLength: 25 berarti KEDA menambah replica setiap 25 pesan menumpuk. Jika satu replica mampu memproses 30 pesan/menit, maka 25 pesan memberi buffer aman tanpa membuat replica menganggur. Turunkan ke 10 untuk responsif; naikkan ke 50 untuk throughput maksimal dengan pod lebih sedikit. Angka ini harus divalidasi dengan benchmark workload nyata.
Tiap provider membatasi jumlah API request. Polling KEDA yang agresif bisa kena rate limit — dan itu membuat metrik gagal dibaca, memicu fallback atau status Unknown (episode 18).
Kasus nyata: SQS ReceiveMessage dibatasi per account, Azure Service Bus punya quota per namespace. KEDA memanggil API tiap pollingInterval untuk setiap scaler. Tiga puluh ScaledObject dengan polling 5 detik = 6 request/detik hanya untuk polling.
Strategi mengatasinya:
curl -s localhost:8080/metrics | grep keda_scaler_errors_total
kubectl logs -n keda deploy/keda-operator | grep -i throttl
kubectl get events -n orders | grep -i throttlJika keda_scaler_errors_total naik dan log menampilkan throttling: naikkan pollingInterval, kurangi jumlah scaler per provider, atau atur minReplicaCount agar replika tidak bolak-balik menyentuh API. Untuk SQS, hindari queueLength terlalu kecil yang membuat replika naik-turun cepat — setiap transisi memicu request tambahan.
Tanpa pengukuran, tuning hanya opini — kubectl get scaledobject -n orders -o yaml hanya menunjukkan status, bukan kinerja. Metodologi yang bisa direproduksi:
1. Definisikan target. Misal: dari antrean kosong, 1000 pesan masuk, dan target semua pesan terproses dalam 5 menit.
2. Ukur komponen latency:
date +%s > /tmp/start # saat pesan dimasukkan ke queue
kubectl get pods -n orders -w # catat kapan replica pertama muncul
kubectl wait --for=condition=ready pod -l app=order-worker -n orders --timeout=120s
date +%s > /tmp/endLatency total = (replica muncul − event masuk) + (pod ready − replica muncul). Komponen pertama adalah pollingInterval + waktu KEDA/HPA + scheduling; komponen kedua adalah pull image + startup container + readiness probe.
3. Breakdown komponen:
| Komponen | Biasanya | Pengaruh tuning |
|---|---|---|
| Polling + HPA reaction | 10-60 detik | pollingInterval, behavior.scaleUp |
| Node provisioning (Karpenter) | 30-90 detik | NodePool, spot availability |
| Image pull + container start | 10-120 detik | Image size, startup probe |
| Readiness | 1-60 detik | Probe tuning |
4. Uji iterasi. Ulangi dengan pollingInterval berbeda dan catat di tabel. Jangan ubah dua variabel sekaligus.
Setiap tuning adalah trade-off antara biaya dan kecepatan respons. Scale-to-zero menghemat biaya tetapi membayar cold start; minReplicaCount: 0 vs minReplicaCount: 2 adalah perbandingan langsung:
spec:
minReplicaCount: 0 # hemat biaya, bayar cold start tiap burst
maxReplicaCount: 30spec:
minReplicaCount: 2 # selalu siap, biaya idle kecil tapi pasti
maxReplicaCount: 30Rumus pengambilan keputusan: jika (frekuensi burst × cold start) melanggar SLO, gunakan warm minimum. Jika burst jarang dan latensi tambahan ditoleransi, scale-to-zero. Data dari benchmark menentukan angka optimal — misal minReplicaCount: 1 cukup untuk memotong separuh cold start karena image sudah hangat di node.
Warning
Jangan mengubah banyak parameter sebelum benchmark stabil. Satu variabel per iterasi, tulis datanya, baru putuskan. Tuning tanpa data hanyalah menukar satu asumsi dengan asumsi lain.
keda_scaler_errors_total saat tuning. Error provider diam-diam merusak baseline benchmark.Episode ini menutup fase tuning: pollingInterval dan cooldownPeriod adalah dua kenop utama, queueLength menentukan saturation per replica yang harus dihitung dari data, throttling provider adalah batas fisik yang harus dihormati, dan benchmark memberikan angka nyata untuk latency scale-up serta cold start. Trade-off biaya vs responsivitas akhirnya bisa diambil berdasarkan tabel data, bukan intuisi.
Poin yang harus kalian bawa:
queueLength harus berasal dari throughput nyata satu replica.keda_scaler_errors_total dan log operator.minReplicaCount.Kita baru saja menyelesaikan seluruh fase inti — dari pre-requisites, operator, scaler, hingga tuning. Di episode 20 selanjutnya kita membahas Fitur Stabil Terbaru (v2.20): evolusi rilis KEDA v2.x, fitur-fitur 2026, perbaikan stability, dan sekilas roadmap v3. Sampai jumpa di episode 20!