Menghadapi kenyataan bahwa jaringan bisa gagal di tengah jalan: teorema CAP dan konsistensi, partitioning, retry dengan backoff yang benar, circuit breaker, hingga idempotency — dibuktikan dengan praktik menerapkan pola resiliency langsung dalam kode

Semua episode sebelumnya mengasumsikan satu hal yang ternyata salah: bahwa ketika kalian memanggil service lain, ia selalu merespons. Kenyataan sistem terdistribusi lebih kasar — jaringan bisa menunda paket, memutus koneksi, dan mengirim respons ganda. Kode yang ditulis untuk dunia "selalu berhasil" akan gagal di dunia nyata, bukan karena bug, tapi karena asumsi.
Distributed systems reliability adalah keterampilan menulis kode yang toleran terhadap kenyataan. Episode 21 membahas konsistensi, partitioning, retry/backoff, circuit breaker, dan idempotency — lima pola yang mengubah service dari rapuh menjadi tangguh di jaringan yang tidak bisa dipercaya.
Teorema CAP menyatakan sistem terdistribusi hanya bisa menjamin dua dari tiga: Consistency (semua node melihat data sama), Availability (setiap request mendapat respons), dan Partition tolerance (sistem tetap jalan saat jaringan terbelah). Karena network partition (P) tidak bisa dicegah, pilihan nyata tinggal dua: saat jaringan terbelah, sistem CP mengorbankan ketersediaan demi konsistensi, dan sistem AP mengorbankan konsistensi demi tetap melayani.
Pilihan ini harus sadar dan tercatat, bukan kebetulan arsitektur: database yang kuat konsistensinya (PostgreSQL, Spanner) adalah CP; system yang akhirnya konsisten (Cassandra, DynamoDB mode default) adalah AP. Kalian harus bisa menjawab dengan satu kalimat: saat node terisolasi, sistem kita memilih menolak tulis atau menerima tulis yang mungkin basi?
Ketika satu request gagal, godaan pertama adalah mencoba lagi segera. Itu justru pola paling berbahaya: jika dependency sedang mati, ribuan request yang me-retry serentak menghasilkan retry storm yang menghabisi dependency yang sedang berusaha pulih.
Aturan retry yang sehat:
Attempt 1: 1.0 + 0.4 jitter = 1.4
Attempt 2: 2.0 + 1.1 jitter = 3.1
Attempt 3: 4.0 + 0.6 jitter = 4.6
Attempt 4: 8.0 + 2.3 jitter = 10.3
Attempt 5: menyerah -> panggil fallbackRetry menyelamatkan kegagalan sementara; circuit breaker menyelamatkan dari kegagalan berkepanjangan. Idenya dipinjam dari listrik: jika kegagalan melampaui ambang batas, putuskan aliran — request langsung ditolak tanpa memanggil dependency, memberi waktu dependency pulih.
CLOSED -> semua request diteruskan (normal)
OPEN -> request ditolak langsung (dependency sakit)
HALF-OPEN-> kirim beberapa percobaan uji (uji pemulihan)Manfaat gandanya: dependency yang sedang kolaps tidak dibebani request yang hanya akan menunggu timeout, dan aplikasi merespons cepat dengan error yang jelas alih-alih menggantung sampai timeout.
Retry memunculkan pertanyaan mengerikan: bagaimana jika request pertama berhasil diproses tetapi responsnya hilang? Kalau klien me-retry, operasi yang sama (bayar, transfer, kirim email) bisa terjadi dua kali. Idempotency menjawabnya: operasi boleh dijalankan berulang, tetapi efeknya hanya terjadi sekali.
Implementasi paling umum adalah idempotency key: klien mengirim Idempotency-Key unik, server menyimpan hasil pertama kali key itu diproses, dan untuk key yang sama mengembalikan respons tersimpan tanpa mengeksekusi ulang.
async function processPayment(key, amount) {
const seen = await idemStore.get(key);
if (seen) return seen; // sudah diproses -> balas hasil lama
const result = await charge(amount); // baru: proses sekali
await idemStore.set(key, result, { ttl: "24h" });
return result;
}Pola ini wajib untuk mutasi yang penting (pembayaran, transfer, event). Read tidak butuh idempotency; create dan update paling butuh.
Gabungkan kelima pola pada service lab kalian yang memanggil dependency eksternal:
# dependency sengaja dimatikan
docker stop dependency-service
# request harus ditolak cepat (bukan menggantung)
time curl -s http://localhost:8080/checkout
# -> respons error < 500ms setelah breaker OPENTip
Mulailah dari satu pola yang paling berdampak: timeout eksplisit — ini murah, mudah, dan langsung menghilangkan sebagian besar masalah "menggantung". Setelah timeout konsisten, tambahkan retry + jitter, lalu breaker, lalu idempotency. Menerapkan kelimanya sekaligus di tengah migrasi justru membuat sulit menemukan akar masalah.
Pada episode 21 ini, kalian telah belajar menulis kode yang memercayai kegagalan sebagai bagian dari desain.
Inti yang harus dibawa pulang:
Di episode 22 selanjutnya, kita akan menggandeng AI: AI-assisted operations — anomaly detection, auto-remediation, dan predictive scaling untuk operasi yang semakin otomatis. Sampai jumpa di episode 22!