Materi ini membahas pola pemrosesan request secara asynchronous di level arsitektur aplikasi/API — bukan soal event loop/async programming di level bahasa pemrograman (topik itu ada di catatan 03_Asynchronous_Programming). Fokusnya adalah keputusan desain: kapan sebuah service sebaiknya merespons synchronous (client menunggu hasil akhir) vs asynchronous (client hanya diberi tahu request diterima, hasil sebenarnya menyusul), dan pola-pola apa saja yang dipakai untuk mengetahui hasil eksekusi ketika prosesnya tidak selesai seketika.
Cara Menghubungkan Services: Kenapa Response Diperlukan
Sebuah response dari server ke client diperlukan untuk tiga alasan:
- Menginformasikan request sudah diterima.
- Berisi data yang diperlukan client.
- Berisi informasi kegagalan yang terjadi.
Synchronous API dilakukan dengan cara client menunggu server selesai memproses — disebut juga blocking request. Ini adalah pola standar yang dipakai HTTP & REST: client mengirim request, server menghitung (calculate the response), baru mengirim response kembali; sepanjang waktu itu client diam menunggu.

Masalah: Bagaimana Jika Eksekusi Request Memerlukan Waktu Lama
Slide memberi contoh pengiriman email: request untuk “deliver an email” ternyata butuh melewati banyak service lain secara berurutan — sender’s mail server → mail relay → receiver’s mail server — sebelum akhirnya ada konfirmasi “email received” yang mengalir balik ke client. Jika pola synchronous dipertahankan di sini, client harus menunggu seluruh rangkaian proses tersebut selesai sebelum mendapat response, padahal client mungkin tidak butuh tahu hasilnya secara langsung/real-time — cukup tahu bahwa permintaannya sudah “dipegang” oleh sistem.
Alternatif Asynchronous
Sebagai gantinya, server bisa langsung merespons begitu request diterima (bukan setelah selesai dieksekusi), lalu proses sebenarnya (mengirim email lewat mail relay, dst.) berjalan di belakang layar.
- Pro: client dapat langsung melanjutkan hal lain tanpa harus menunggu proses panjang selesai.
- Cons: client tidak mengetahui apakah request tersebut nantinya benar-benar berhasil dieksekusi atau tidak — response “OK, I’ll try!” hanya berarti request sudah diterima, bukan jaminan sukses.

Perbedaan Makna Response: Synchronous vs Asynchronous
Poin pentingnya: pada kedua kasus, response tetap dikirimkan ke client, dan keduanya bisa sama-sama diimplementasikan dengan HTTP/REST. Perbedaannya bukan pada mekanisme transport, melainkan pada makna semantik dari response itu sendiri:
| Aspek | Synchronous | Asynchronous |
|---|---|---|
| Request | Deliver an email | Deliver an email |
| Makna response | Delivery acknowledge — konfirmasi bahwa email benar-benar sudah terkirim | Request acknowledge — konfirmasi bahwa request sudah diterima, belum tentu sudah dieksekusi |
| Client menunggu hingga | Proses selesai sepenuhnya (blocking) | Request diterima saja (tidak blocking terhadap hasil akhir) |
| Kepastian hasil bagi client | Langsung pasti (sukses/gagal diketahui saat itu juga) | Tidak pasti — perlu mekanisme tambahan untuk tahu hasil akhirnya |
| Kompleksitas desain | Lebih sederhana, mengikuti pola HTTP/REST standar | Lebih kompleks — perlu desain tambahan (status tracking, callback, atau side channel) |
| Kecepatan respons ke client | Lambat jika proses backend lama | Cepat, karena client tidak menunggu proses backend selesai |
| Contoh use case | Query data, validasi login, operasi cepat lainnya | Transfer file besar, pembuatan VM, checkout, booking tiket |
Bagaimana Jika Client Perlu Mengetahui Hasilnya
Model asynchronous yang dijelaskan sebelumnya (kirim request, dapat ACK penerimaan, lalu tidak ada follow-up lagi) disebut pola fire and forget. Namun pada banyak kasus nyata, client tetap perlu tahu hasil akhir dari request yang dikirimkan — apakah sukses, gagal, atau errornya apa. Untuk itu ada tiga opsi/variasi pola yang bisa dipakai di atas dasar fire-and-forget.
Opsi 1: Request Record
Mekanismenya:
- Server menyimpan sebuah request record pada database ketika request pertama kali diterima, lalu mengembalikan sebuah unique request ID ke client.
- Ketika eksekusi request akhirnya selesai (baik sukses maupun gagal), server mengupdate request record tersebut di database dengan status terbaru.
- Client kemudian dapat mengecek hasil kapan saja dengan cara polling menggunakan request ID yang sudah didapat sebelumnya.
Contoh alur konkret dari slide:
POST /messageAttempt → {"email_id": 4390293}
GET /message/status/4390293 → {"status": "pending"}
GET /message/status/4390293 → {"status": "failed", "error": "invalid address"}
Client mengirim request pembuatan pesan, mendapat ID 4390293, lalu berulang kali melakukan GET ke endpoint status menggunakan ID tersebut sampai statusnya berubah dari pending menjadi hasil akhir (failed/success). Pola ini cocok ketika client tidak selalu online mendengarkan, tapi bersedia melakukan polling berkala.
Opsi 2: Callback ke Client (Webhook)
Mekanismenya:
- Client menyediakan fungsi callback (dikenal sebagai webhook) — yaitu sebuah URL/endpoint milik client sendiri — yang disertakan dalam request awal.
- Server, setelah selesai memproses request (berapa pun lama waktunya), secara aktif memanggil balik (POST) ke URL callback tersebut untuk mengirimkan hasil akhirnya.
- Syarat penting: pola ini hanya bisa dilakukan jika client dapat listen response — artinya client harus berupa proses/service yang terus berjalan (long-running) dan dapat diakses dari jaringan (tidak terhalang NAT/firewall di sisi client), karena server-lah yang perlu menginisiasi koneksi baru ke client.
Contoh alur dari slide:
Client sends: POST /messageAttempt
{"callback": "http://3.3.3.3:80/messageComplete"}
... beberapa waktu kemudian ...
Backend sends: POST /messageComplete
Client mengirim request berikut alamat callback-nya, mendapat ACK (“OK, I’ll try!”) segera, lalu di kemudian hari — setelah proses pengiriman email benar-benar selesai — server (backend) balik memanggil endpoint /messageComplete milik client untuk memberi tahu hasilnya.

Opsi 3: Side Channel
Mekanismenya:
- Kita tetap memakai model fire and forget murni sebagai jalur utama — asalkan tingkat kegagalan (failure rate) jarang terjadi.
- Ketika kegagalan memang terjadi, informasi mengenai kegagalan tersebut dikirimkan lewat channel lain di luar jalur request-response utama, bukan lewat status tracking maupun callback.
Contoh konkret dari slide:
- Menggunakan email untuk mengirimkan notifikasi jika terjadi kegagalan pengiriman order (misalnya kegagalan charge kartu kredit pada proses “purchase book”).
- Menyimpan log error untuk keperluan monitoring oleh tim operasional, bukan langsung dikonsumsi oleh client.

Perhatikan bahwa pada diagram di atas, alur normalnya tetap sama seperti fire-and-forget biasa (Purchase book → OK, I'll try!), tapi ada jalur tambahan Email: charge failed yang hanya muncul kondisional saat terjadi kegagalan — inilah “side channel”-nya.
Ringkasan Perbandingan Tiga Pola
| Pola | Mekanisme inti | Siapa yang inisiasi cek status | Syarat/prasyarat | Cocok untuk |
|---|---|---|---|---|
| Request Record | Simpan status di DB + request ID, client polling | Client (aktif mengecek) | Client tahu request ID, mau polling | Client tidak selalu online, hasil tidak butuh notifikasi instan |
| Callback (Webhook) | Server memanggil balik URL callback milik client | Server (aktif memberi tahu) | Client harus long-running & reachable dari jaringan (tidak di belakang NAT/firewall) | Integrasi antar service/backend, client berupa server lain |
| Side Channel | Fire-and-forget, notifikasi kegagalan lewat channel lain (email, log) | Server, tapi hanya saat gagal | Failure rate harus jarang | Operasi yang umumnya reliable, kegagalan adalah kasus minoritas |
Contoh Request yang Cocok Menggunakan Asynchronous Processing
Beberapa jenis request yang secara alami cocok diproses secara asynchronous karena butuh waktu lama, melibatkan banyak resource, atau hasilnya tidak perlu diketahui client secara instan:
- Transfer file (terutama file besar).
- Mengambil file dari tape storage (media penyimpanan lambat).
- Pembuatan virtual machine (misalnya pada cloud provider).
- Membeli barang pada shopping cart (checkout).
- Book tiket pesawat, bioskop, atau konser.
- Request connection pada social media (permintaan pertemanan/follow).
- Pengiriman mobile push notification ke user lain.
- Pengiriman text/SMS.
- Copy sebuah tweet ke ribuan/jutaan followers.
Message Queue: Menyediakan Asynchronicity & Decoupling
Jika client benar-benar tidak perlu status response (fire and forget murni), request cukup disimpan pada sebuah queue untuk diproses nanti oleh service lain, alih-alih diproses langsung saat itu juga.
Keuntungan menambahkan pesan ke queue:
- Cepat, karena operasinya hanya berupa kopi data ke antrian — tanpa parsing atau eksekusi business logic sama sekali di titik ini.
- Menghindari perlambatan pada upstream service akibat kepadatan di downstream — artinya service yang menerima request awal (upstream) tidak ikut melambat meskipun service yang benar-benar memproses (downstream) sedang sibuk/tertunda. Queue berperan sebagai buffer sehingga sistem dapat menangani burst pendek (lonjakan request sesaat) yang sebenarnya melebihi kapasitas pemrosesan normal sistem.
Message Queue Menyimpan Request yang Siap Diproses
Konsep pentingnya: menyimpan request pada queue itu esensinya sama seperti membuat sebuah request API biasa.
- Isi dari pesan (message) itu sendiri yang mendefinisikan request-nya — bisa dianggap message format == API.
- Artinya, aturan/skema format pesan yang disepakati berfungsi sama seperti kontrak API — producer dan consumer harus sepakat soal struktur data di dalam pesan, persis seperti API contract antara client dan server.
Queue Terminology
- Producer: pihak yang push/publish/produce message ke queue.
- Consumer: pihak yang pull/pop/consume/subscribe message dari queue.
- Sebuah message queue dapat dipartisi menjadi beberapa virtual queue dengan cara mendefinisikan topic pada setiap pesan — sehingga consumer dapat subscribe hanya pada topic tertentu saja, tidak harus menerima semua pesan yang masuk ke queue.
Contoh Kasus: Alur Publish Tweet dengan Message Queue
Slide memberi contoh end-to-end yang menunjukkan bagaimana beberapa queue bisa dirangkai bertahap dalam satu arsitektur:
- Client posts request — mobile app mengirim
POST /tweetke Twitter API. API service (a) mengirim request ke auth service untuk validasi token (auth service mengecek ke Account DB), (b) menyimpan job post tweet ke work queue untuk diproses belakangan, lalu (c) langsung mengirim response sukses200 OKke user — semua ini terjadi sebelum tweet benar-benar dipublikasikan ke followers. - Publication service memproses request — service ini mengambil job dari work queue, mengambil daftar followers dari Followers DB, menambahkan tweet baru ke semua follower’s feed (disimpan di Feed DB), lalu mengantrikan task baru ke notification queue untuk memberi notifikasi ke setiap
@mentiondan followers yang mengaktifkan alert. - Notification service memberikan alert ke user — mengambil task dari notification queue satu per satu (bisa 0 hingga jutaan item tergantung jumlah followers/mentions), lalu mengirimkan notifikasi lewat email/mobile device (data diambil dari email & mobile dev. DB). Jika terjadi kegagalan pengiriman notifikasi, task diulang beberapa kali, dan jika tetap gagal, bisa diabaikan — konsisten dengan sifat notifikasi yang best-effort, bukan critical.

Pola ini menunjukkan bagaimana satu request awal (POST /tweet) di-decouple menjadi rangkaian tahapan independen yang masing-masing punya queue-nya sendiri (work queue → notification queue), sehingga setiap tahap bisa diproses dan di-scale terpisah tanpa membuat client menunggu keseluruhan rangkaian selesai.
Tradeoff: Tightly Coupled vs Loosely Coupled
- Tightly coupled (synchronous) service lebih mudah dirancang dan dibangun — alurnya linear dan mudah dipahami: request masuk, diproses, response keluar, selesai.
- Loosely coupled (asynchronous) service dapat lebih cepat (dari sudut pandang client yang tidak perlu menunggu proses penuh), namun perlu strategi eksplisit untuk menangani kegagalan, karena kegagalan tidak lagi otomatis terlihat oleh client saat itu juga. Tiga opsi penanganan kegagalan pada model asynchronous:
- Kegagalan dapat ditolerir/diabaikan — dianggap acceptable loss (relevan untuk kasus seperti notifikasi non-kritis).
- Error disimpan pada DB untuk dicek kemudian — namun ini berarti lebih sulit melakukan penanganan error secara tepat waktu (delayed error handling).
- Error dapat menimbulkan semacam alert ke user — mirip pola side channel yang sudah dibahas sebelumnya.
| Aspek | Tightly Coupled (Synchronous) | Loosely Coupled (Asynchronous) |
|---|---|---|
| Kemudahan desain & implementasi | Lebih mudah — alur linear, mengikuti pola HTTP/REST standar | Lebih kompleks — perlu desain tambahan (queue, status tracking, callback) |
| Kecepatan respons ke client | Terbatas oleh waktu proses backend (client menunggu penuh) | Cepat — client hanya menunggu ACK penerimaan |
| Visibilitas kegagalan | Langsung terlihat client saat itu juga (dalam response) | Tidak langsung; butuh mekanisme tambahan (request record/callback/side channel) atau ditoleransi |
| Ketergantungan antar service | Erat (tightly coupled) — kegagalan downstream langsung memengaruhi caller | Longgar (loosely coupled) — service dapat berjalan/gagal independen berkat buffer queue |
| Skalabilitas | Sulit menyerap burst request karena tiap request menahan resource sampai selesai | Lebih mudah menyerap burst — queue meredam lonjakan (smoothing) |
| Contoh penggunaan | REST API standar, validasi login, query data | Transfer file besar, pembuatan VM, checkout, booking tiket, publish tweet ke jutaan follower |
Decoupling Mendukung Scalability
Message queue pada dasarnya adalah sejenis database sederhana yang tugas utamanya menyimpan request/job. Karakteristik penting yang mendukung skalabilitas:
- Many producers dan many consumers dapat tersambung ke satu queue yang sama secara bersamaan.
- Basic queue berjalan pada satu mesin, sedangkan distributed queue berjalan pada cluster (banyak mesin).
- Queue dapat berperan sebagai semacam load balancer — mendistribusikan pekerjaan ke banyak consumer.
- Producer dan consumer dapat di-scale secara independen — jumlah producer dan jumlah consumer tidak harus sama atau berubah bersamaan; masing-masing bisa ditambah/dikurangi sesuai bebannya sendiri.
- Queue smooths/melandaikan peak permintaan dengan cara menunda pemrosesan — request yang masuk saat beban tinggi tetap ditampung di queue, tidak langsung ditolak atau membuat sistem downstream kewalahan.

Active vs Passive Queue
| Aspek | Active Queue | Passive Queue |
|---|---|---|
| Arah pengiriman pesan | Queue mengetahui kemana harus mengirim pesan dan secara aktif melakukan push ke subscriber | Queue hanya menerima dan menyimpan pesan hingga diminta — tidak tahu/tidak peduli siapa yang akan mengambilnya |
| Peran consumer/subscriber | Harus listen message yang dikirim (event-driven) | Harus secara periodik melakukan request/poll pesan sendiri |
| Pola push/pull | Producer pushes, dan queue pushes ke consumer | Producer pushes, tapi consumer pulls |
| Analogi implementasi | Sistem notifikasi/event bus | Specialized DB — bisa diimplementasikan sebagai DB table biasa |
Queue pada Berbagai Level Arsitektur
Ada tiga level di mana konsep queue dapat diimplementasikan, dari yang paling sederhana hingga paling kompleks:
- In-app queue — sebuah aplikasi membuat queue internal untuk menyimpan job yang akan dikerjakan belakangan, mungkin dieksekusi pada thread yang berbeda dalam proses yang sama. Contoh:
ExecutorServicepada Java yang di dalamnya berisi work queue. - Separate queueing app — sebuah proses terpisah yang berjalan dan siap melakukan push/fetch pesan melalui koneksi jaringan. Seringkali proses ini dijalankan pada node yang sama dengan aplikasi utama, sehingga tetap bisa memakai komunikasi lokal (lebih cepat, tapi masih proses yang berbeda).
- Distributed message queue — sebuah cluster yang mengimplementasikan queue yang scalable dan robust. Contoh: ActiveMQ, Kafka, RabbitMQ, AWS SQS.
Pros & Cons Tiap Level
| Level | Pros | Cons |
|---|---|---|
| In-app queue | Sederhana; tidak memerlukan deployment aplikasi lain | Umumnya tidak persisten — saat aplikasi crash, message yang ada di queue dapat hilang |
| Separate queueing app | Dapat dijalankan pada VM yang sama dengan aplikasi utama; dapat menyimpan message ke file (lebih persisten dari in-app) | Scalability terbatas satu mesin; kegagalan machine/disk dapat membuat message hilang |
| Distributed message queue | Massively scalable; messages direplikasi pada banyak node; menyediakan satu titik koordinasi yang sama untuk semua producer & consumer | Complexity tinggi; ada consistency side effect — misalnya pada RabbitMQ, kita harus memilih delivery guarantee “at least once” atau “at most once”, namun tidak bisa “exactly once” |
Back Pressure
Pertanyaan kuncinya: apa yang terjadi jika queue penuh?
- Queue mungkin memberikan pesan error saat producer mencoba menambahkan entri baru ke queue yang sudah penuh.
- Hal ini dapat mengakibatkan layanan terhenti atau error di sisi producer/upstream.
- Devops/operations harus memonitor ukuran queue secara berkelanjutan untuk mengantisipasi masalah ini sebelum terjadi.
- Pada autoscaling system, jumlah worker/backend (consumer) dapat di-scale otomatis berdasarkan panjang queue — semakin panjang antrian, semakin banyak consumer yang dijalankan untuk mengejar backlog.
Singkatnya, back pressure adalah mekanisme “sinyal balik” ketika kapasitas queue terlampaui: pilihannya adalah scaling (tambah consumer/kapasitas) atau reject dengan error (menolak request baru sampai ada ruang).
Catatan Penting: Queue Bukan Pengganti Frontend
Message Queue memiliki perilaku seperti layanan backend lain (misalnya database) — tidak dirancang untuk menerima koneksi langsung dari ribuan client sekaligus. Karena itu, arsitektur yang benar tetap harus punya frontend/API service yang menerima request dari client (biasanya lewat HTTP/REST), lalu service itulah yang menyimpan request tersebut ke queue — bukan client yang langsung berkomunikasi dengan message queue.
Flashcard
flashcards Apa perbedaan makna response antara synchronous dan asynchronous processing, meskipun keduanya sama-sama bisa dikirim lewat HTTP/REST? :: Pada synchronous, response berarti “delivery acknowledge” (proses benar-benar sudah selesai/berhasil); pada asynchronous, response hanya berarti “request acknowledge” (request sudah diterima, belum tentu sudah dieksekusi/berhasil). Apa itu pola “fire and forget”, dan apa masalah utamanya? :: Pola di mana client hanya mengirim request dan mendapat ACK penerimaan tanpa follow-up lebih lanjut. Masalah utamanya: client tidak pernah tahu apakah request tersebut akhirnya benar-benar berhasil dieksekusi atau gagal. Jelaskan mekanisme pola Request Record untuk mengetahui hasil asynchronous request. :: Server menyimpan request record di database dan mengembalikan unique request ID ke client saat request diterima; setelah eksekusi selesai, server mengupdate record tersebut; client kemudian melakukan polling (GET) menggunakan request ID untuk mengecek status terkini (pending/success/failed). Apa syarat utama agar pola Callback (webhook) bisa dipakai, dan bagaimana mekanismenya? :: Client harus menyediakan URL callback dan harus bisa listen response — artinya client harus long-running dan reachable dari jaringan (tidak terhalang NAT/firewall). Server, setelah selesai memproses, secara aktif memanggil balik (POST) ke URL callback tersebut untuk mengirim hasil. Kapan pola Side Channel cocok dipakai, dan berikan contohnya. :: Cocok ketika failure rate jarang terjadi, sehingga model fire-and-forget tetap dipertahankan sebagai jalur utama, dan informasi kegagalan (jika terjadi) dikirim lewat channel lain di luar jalur utama — misalnya notifikasi email saat charge kartu gagal, atau pencatatan log error untuk monitoring. Mengapa menambahkan pesan ke message queue itu cepat, dan apa manfaatnya bagi upstream service? :: Karena menambahkan pesan ke queue hanya berupa kopi data tanpa parsing atau eksekusi business logic. Manfaatnya, upstream service tidak ikut melambat akibat kepadatan di downstream, sehingga sistem bisa menyerap burst request pendek yang melebihi kapasitas normal. Apa perbedaan active queue dan passive queue? :: Active queue mengetahui tujuan pengiriman dan secara aktif push pesan ke subscriber (subscriber harus listen); passive queue hanya menerima dan menyimpan pesan hingga diminta, sehingga consumer harus secara periodik melakukan poll/pull sendiri (queue berperan seperti specialized DB/DB table). Sebutkan tiga level arsitektur penggunaan queue beserta satu contohnya masing-masing. :: In-app queue (contoh: ExecutorService pada Java), separate queueing app (proses terpisah yang push/fetch lewat koneksi jaringan, sering di node yang sama), dan distributed message queue (cluster scalable, contoh: ActiveMQ, Kafka, RabbitMQ, AWS SQS). Apa itu back pressure pada message queue, dan apa dua opsi penanganannya? :: Back pressure adalah kondisi ketika queue penuh sehingga producer bisa menerima error saat menambah entri baru. Dua opsi penanganannya: melakukan scaling (menambah consumer/kapasitas berdasarkan panjang queue, misalnya lewat autoscaling) atau menolak (reject) request baru dengan error. Mengapa message queue tidak bisa langsung menggantikan API service sebagai penerima request dari client? :: Karena message queue berperilaku seperti layanan backend lain (mis. database) yang tidak dirancang menerima koneksi langsung dari ribuan client sekaligus, sehingga tetap dibutuhkan frontend/API service yang menerima request client lalu menyimpannya ke queue.