Bab lalu kita sepakat: mulai bab ini, Order Service dan Inventory Service adalah dua service terpisah yang cuma bisa bicara lewat network, bukan pemanggilan fungsi langsung. Pertanyaan yang langsung muncul begitu ada dua service: kalau Order Service butuh tahu stok sebuah item dari Inventory Service, apa yang terjadi selama itu berlangsung — apakah Order Service berhenti dan menunggu, atau jalan terus?
Itu pertanyaan tentang gaya komunikasi, dan ada dua jawaban besar: sinkron dan asinkron. Bab ini membahas keduanya secara konsep, supaya waktu kita menulis kode service-to-service call di bab 29, kamu paham betul kenapa kodenya berbentuk seperti itu — bukan cuma menyalin pola tanpa tahu alasannya.
Komunikasi Sinkron — Caller Menunggu
Komunikasi sinkron (lewat REST atau gRPC) bekerja seperti percakapan telepon: kamu bertanya, lalu diam menunggu sampai lawan bicara menjawab, baru kamu lanjut ke langkah berikutnya. Dalam istilah kode: InventoryClient di Order Service memanggil endpoint HTTP milik Inventory Service, dan thread yang menjalankan request itu berhenti (blocked) sampai responsnya datang — entah itu data stok, error, atau timeout.
Kelebihannya jelas kelihatan:
- Model mental sederhana. Kamu menulis kode yang terbaca top-to-bottom: panggil, dapat hasil, lanjut. Tidak ada callback, tidak ada "nanti dikabari lewat channel lain".
- Hasilnya langsung ada. Kalau Order Service butuh tahu stok sekarang juga untuk ditampilkan ke user, sinkron adalah satu-satunya pilihan yang masuk akal — tidak ada cara untuk "menampilkan jawaban nanti" pada satu request HTTP yang sama.
Tapi ada harga yang harus dibayar, dan ini poin paling penting di bab ini: komunikasi sinkron mengikat ketersediaan caller ke ketersediaan callee. Kalau Inventory Service down atau lambat, Order Service ikut kena imbasnya — bisa dalam bentuk request yang menggantung lama, atau (kalau tidak hati-hati) thread Order Service yang habis semua karena menunggu balasan yang tidak pernah datang. Ini persis kekhawatiran yang kita singgung di bab 25 soal "kegagalan menjalar dari satu service ke service lain" — dan ini juga alasan kenapa nanti di bab 29, InventoryClientConfig di Order Service wajib mengatur timeout eksplisit. Tanpa timeout, satu Inventory Service yang macet bisa menahan Order Service tanpa batas waktu.
Komunikasi Asinkron — Caller Tidak Menunggu
Komunikasi asinkron bekerja lewat perantara — biasanya message broker seperti Kafka atau RabbitMQ. Alih-alih menelepon langsung, caller menitipkan pesan ke broker ("event ini baru saja terjadi") lalu langsung lanjut ke pekerjaan berikutnya, tanpa menunggu siapa pun membaca pesan itu. Service lain yang berkepentingan akan membaca pesan itu sendiri, kapan pun mereka siap — bisa sepersekian detik kemudian, bisa juga beberapa menit kemudian kalau mereka sedang sibuk atau baru saja pulih dari down.
Kelebihannya adalah kebalikan dari kelemahan sinkron:
- Decoupling ketersediaan. Kalau service pembaca pesan sedang down, pesan tetap aman tersimpan di broker, menunggu dibaca begitu service itu hidup lagi. Publisher tidak pernah tahu — dan tidak perlu tahu — bahwa pembacanya sempat mati.
- Caller tidak pernah tertahan menunggu service lain. Ini sangat berharga untuk operasi yang tidak butuh jawaban seketika — misalnya "kirim notifikasi setelah pembayaran berhasil" tidak perlu membuat proses pembayaran menunggu notifikasi selesai terkirim.
Tapi asinkron juga bukan gratis. Alur data jadi lebih sulit ditelusuri — satu proses bisnis bisa melompat lewat beberapa event yang dipublish dan dikonsumsi di waktu berbeda, dan melacak "kenapa data ini belum ter-update" butuh alat bantu yang lebih rumit dibanding sekadar membaca stack trace satu request HTTP. Ada juga masalah baru yang tidak muncul di dunia sinkron, seperti memastikan sebuah pesan tidak diproses dua kali (idempotency) atau menjaga agar penulisan ke database dan publish event ke broker tetap konsisten (outbox pattern).
Fase Ini Hanya Pakai Sinkron
Supaya jelas dan tidak menimbulkan ekspektasi salah: Fase 4 — termasuk semua kode yang akan kamu tulis di bab 27-29 — hanya menggunakan komunikasi sinkron. Order Service memanggil Inventory Service langsung lewat HTTP (RestClient), menunggu jawabannya, dan bereaksi berdasarkan hasil itu (atau ketiadaannya). Tidak ada broker, tidak ada Kafka, tidak ada RabbitMQ di fase ini.
Ini keputusan desain yang disengaja, bukan keterbatasan. Sistem dua-service yang kita bangun cukup sederhana sehingga sinkron adalah pilihan yang wajar: cek stok itu operasi yang butuh jawaban seketika (ditampilkan langsung ke pengguna), bukan sesuatu yang bisa "menyusul nanti". Materi event-driven messaging dengan Kafka — termasuk outbox pattern dan idempotency yang disinggung di atas — masuk ke Fase 5, yang roadmap-nya sudah dirancang tapi belum ditulis jadi bab artikel. Anggap saja bab ini sebagai peta jalan: kamu sekarang tahu di mana letak sinkron dan asinkron dalam gambaran besar, meski yang kita praktikkan langsung di sini baru separuhnya.
Yang Akan Kita Bangun di Tiga Bab Berikutnya
Dengan pilihan sinkron sudah ditetapkan, tiga bab berikutnya di fase ini akan membangun sistem dua-service secara bertahap dan konkret:
- Bab 27 — sebelum menulis satu baris kode implementasi pun, kita akan mendesain dulu bentuk kontrak API Inventory Service lewat OpenAPI — pendekatan yang disebut contract-first.
- Bab 28 — kita bangun Gateway Service sebagai satu pintu masuk publik (port 8080) yang meneruskan request ke Order Service atau Inventory Service, supaya client tidak perlu tahu port masing-masing service.
- Bab 29 — kita masuk ke inti fase ini: kode
RestClientdi Order Service yang benar-benar memanggil Inventory Service, lengkap dengan timeout dan penanganan kegagalan — bab penutup dari seluruh seri 29 bab ini.
Bagian dari Series: Kotlin Backend Microservice - Belajar Fundamental sampai Microservice Nyata
Belajar Kotlin + Spring Boot dari fundamental bahasa (null safety, OOP, coroutines) sampai membangun sistem microservice sungguhan - REST API, Postgre...
Lihat Series Lengkap