MQTT dan QUIC Menyelesaikan Bagian Berbeda dari Transport Chat

MQTT dan QUIC sering ditempatkan dalam tabel perbandingan yang sama ketika membahas chat real-time. Perbandingan itu praktis, tetapi mencampur dua layer protokol yang berbeda menjadi satu pilihan.

MQTT adalah protokol messaging pada application layer. Ia mendefinisikan konsep seperti client, broker, topic, subscription, retained message, session state, dan quality of service untuk delivery. QUIC adalah protokol transport aman di atas UDP. Ia menyediakan connection, stream, flow control, loss recovery, encryption, dan mekanisme connection migration.

Karena itu, sistem chat dapat memakai MQTT tanpa QUIC, QUIC tanpa MQTT, atau protokol messaging yang dibawa oleh transport yang berkembang secara terpisah. Arsitekturnya lebih mudah dianalisis ketika tanggung jawab tersebut dipisahkan.

MQTT mendefinisikan semantik messaging

Client MQTT bertukar control packet dengan server MQTT yang lazim disebut broker. Publisher mengirim pesan ke nama topic; subscriber mendaftarkan topic filter dan menerima publication yang cocok.

Pemetaan chat yang disederhanakan dapat terlihat seperti ini:

phone A
   |
   | PUBLISH chat/42
   v
 broker
   |
   | matching subscription
   v
phone B

Model tersebut menjawab pertanyaan pada application layer. Ke mana pesan dipublikasikan? Subscriber mana yang harus menerimanya? Apakah session state bertahan setelah reconnect? Perilaku acknowledgement apa yang diminta?

MQTT juga mendefinisikan tiga level Quality of Service:

  • QoS 0: at most once;
  • QoS 1: at least once;
  • QoS 2: exactly once delivery antara peer protokol MQTT untuk pertukaran yang relevan.

Label tersebut tidak otomatis menjadi jaminan chat end-to-end. Broker yang mengakui sebuah publication bukan berarti perangkat penerima sudah menampilkannya, menyimpannya, atau penggunanya sudah membaca pesan. Aplikasi chat tetap membutuhkan message identifier dan state transition sendiri jika menampilkan status sent, delivered, dan read.

QUIC mendefinisikan perilaku transport

QUIC bekerja di bawah application protocol. Ia menyediakan connection aman antara endpoint dan membawa satu atau lebih stream di dalam connection tersebut.

application protocol
   |       |       |
stream 0 stream 4 stream 8
   \       |       /
        QUIC
          |
         UDP

TLS terintegrasi ke dalam handshake QUIC. QUIC juga menangani congestion control, reliable delivery untuk stream, loss detection, dan flow control.

Model stream penting karena packet loss pada satu stream tidak memaksa stream lain menunggu byte yang hilang dari stream tersebut. TCP mengekspos satu ordered byte stream, sehingga segmen TCP yang hilang dapat menunda byte berikutnya pada connection yang sama meskipun aplikasi menganggap data tersebut sebagai pesan yang tidak saling bergantung.

Di sinilah perbedaan head-of-line yang relevan. Pernyataan sederhana bahwa “QUIC tidak memiliki head-of-line blocking” terlalu luas: byte di dalam satu QUIC stream tetap berurutan. Keuntungannya adalah loss pada satu stream tidak memberlakukan transport-level ordering kepada semua stream lain dalam connection.

HTTP/3 bukan nama lain untuk QUIC

HTTP/3 menggunakan QUIC sebagai transport. Keduanya bukan nama yang dapat dipertukarkan.

HTTP/3
  |
 QUIC
  |
 UDP

HTTP/3 mendefinisikan semantik HTTP seperti request, response, field, dan penggunaan stream khusus HTTP. QUIC menyediakan transport di bawahnya.

Protokol chat custom juga dapat berjalan langsung di atas QUIC tanpa HTTP/3, tetapi pendekatan tersebut berarti tim harus memiliki lebih banyak desain dan implementasi protokol sendiri. Sebaliknya, aplikasi dapat menggunakan HTTP/3 untuk API dan trafik media biasa sambil mempertahankan channel berbeda untuk event real-time.

Jadi pertanyaan arsitekturalnya bukan sekadar “MQTT atau HTTP/3”. Pertanyaannya adalah semantik messaging apa yang diperlukan aplikasi dan transport apa yang tepat untuk setiap kelas trafik.

MQTT di atas TCP mewarisi perilaku connection TCP

Deployment MQTT lazim berjalan di atas TCP, biasanya dilindungi TLS ketika trafik melewati jaringan yang tidak dipercaya. Dalam susunan tersebut, MQTT mewarisi perilaku ordered byte stream milik TCP.

Jika satu segmen TCP hilang, byte setelahnya belum dapat diberikan kepada parser MQTT sampai byte yang hilang dipulihkan. Topic MQTT tidak menciptakan transport stream independen. Publication ke typing/42 dan publication ke chat/42 dapat tidak saling bergantung secara logis, tetapi ketika berbagi satu connection TCP keduanya tetap melewati ordered byte stream yang sama.

Hal itu tidak otomatis menjadi masalah. Pesan chat umumnya kecil, dan persistent TCP connection menghindari setup connection berulang. Framing MQTT yang ringkas serta model session jangka panjang dapat cocok untuk client yang constrained atau sistem yang berorientasi event.

Poin pentingnya: topic multiplexing dan transport multiplexing adalah dua properti yang berbeda.

Connection migration mengubah perilaku kegagalan di mobile

Client mobile rutin berpindah antara Wi-Fi dan jaringan seluler. Connection TCP diidentifikasi oleh informasi endpoint jaringan yang mencakup alamat IP dan port. Perubahan path yang membuat connection tersebut tidak lagi valid biasanya mengharuskan aplikasi reconnect dan memulihkan session state yang diperlukan.

QUIC dirancang agar connection tidak diidentifikasi hanya oleh network tuple tradisional. Connection ID memungkinkan connection bertahan melewati perubahan path yang didukung, dengan tetap bergantung pada perilaku endpoint, path validation, dan kondisi jaringan.

Kemampuan ini dapat mengurangi biaya transisi jaringan pada aplikasi mobile. Namun, application session recovery tetap diperlukan. Perangkat masih dapat offline cukup lama hingga state server kedaluwarsa, kehilangan credential, restart, atau bertemu intermediary yang menghalangi path pilihan. Durable chat state tetap harus berada di atas transport.

MQTT menangani bagian lain dari masalah recovery melalui session semantics. Bergantung pada versi MQTT dan setting yang dinegosiasikan, server dapat mempertahankan session state yang relevan melewati reconnect jaringan. QUIC dapat mempertahankan transport connection pada sebagian perubahan path; MQTT dapat mempertahankan messaging state ketika transport connection baru dibuat. Keduanya adalah mekanisme yang saling melengkapi.

Delivery semantics membutuhkan boundary aplikasi

Layanan chat produksi biasanya memiliki beberapa boundary acknowledgement yang berbeda:

sender
  |
  | accepted
  v
server
  |
  | delivered
  v
recipient device
  |
  | read
  v
recipient UI

Transport acknowledgement hanya membuktikan sesuatu tentang transport delivery. MQTT QoS acknowledgement membuktikan penyelesaian pertukaran packet MQTT yang telah didefinisikan antara peer protokol. Keduanya tidak dengan sendirinya membuktikan bahwa pengguna akhir sudah membaca pesan.

Karena itu, protokol chat umumnya membutuhkan application message ID dan state transition eksplisit. Retry kemudian dapat dikenali sebagai pesan logis yang sama, bukan dimasukkan sebagai pesan kedua.

Contohnya:

message_id = 8f31...

client -> server: SEND 8f31
client <- server: ACCEPTED 8f31
server -> device: MESSAGE 8f31
server <- device: DELIVERED 8f31
server <- device: READ 8f31

Format wire yang tepat bukan bagian terpenting. Properti yang berguna adalah setiap acknowledgement menyebut boundary yang sudah dilewatinya.

Broker adalah pilihan arsitektur, bukan bottleneck otomatis

Model broker MQTT kadang dianggap tidak cocok untuk chat berskala besar karena “broker akan menjadi bottleneck.” Kesimpulan itu tidak mengikuti protokolnya secara otomatis.

Satu proses broker memiliki kapasitas terbatas, sama seperti satu server HTTP atau QUIC. Sistem MQTT produksi dapat mempartisi pekerjaan, membuat cluster broker, mendistribusikan subscription, dan menempatkan infrastruktur connection dekat dengan client. Scaling tetap memerlukan penanganan routing, session ownership, fan-out, persistence, ordering, dan failure recovery secara hati-hati.

Model broker memang membawa konsekuensi arsitektural. Server ikut melakukan routing publication dan mengelola subscription state. Model itu dapat berguna untuk device telemetry dan distribusi event, sementara layanan chat mungkin memilih routing domain-specific yang terikat langsung dengan conversation, inbox, abuse control, storage, dan metadata encryption.

Keputusan seharusnya mengikuti state model, bukan anggapan bahwa publish-subscribe pasti scalable atau pasti gagal ketika skala membesar.

Media tidak perlu dipaksa melewati jalur kontrol real-time

Aplikasi chat modern menangani payload yang sangat berbeda:

typing indicator       puluhan byte
message event          kecil
delivery receipt       kecil
image                   besar
video                   sangat besar
voice/video call       media kontinu

Tidak ada keharusan memakai satu protokol untuk semuanya.

Desain praktis dapat mempertahankan control event kecil pada persistent real-time connection, sementara object besar diunggah melalui infrastruktur HTTP dan hanya metadata object yang dikirim melalui messaging channel.

                  +--> real-time channel --> message events
client -----------+
                  +--> HTTP/CDN -----------> images, video, files

Pemisahan ini tidak bergantung pada apakah real-time channel memakai MQTT, WebSocket, protokol custom di atas QUIC, atau transport lain.

End-to-end encryption berada di atas keduanya

TLS melindungi data selama melintasi transport connection. MQTT over TLS dan QUIC sama-sama dapat menyediakan transport security sesuai security model masing-masing, tetapi transport encryption berakhir pada transport endpoint.

End-to-end encryption untuk chat memiliki boundary berbeda. Isi pesan dienkripsi sehingga intermediary application server tidak dapat mendekripsi payload yang dilindungi. Mekanisme tersebut membutuhkan application cryptographic protocol yang menangani key establishment, device identity, message encryption, replay handling, dan sering kali multi-device state.

plaintext
   |
E2EE encrypt
   |
ciphertext
   |
MQTT / HTTP / custom messaging
   |
TLS atau QUIC transport

Mengganti TCP dengan QUIC tidak menciptakan end-to-end encryption. Mengadopsi MQTT juga tidak menghalangi aplikasi untuk menerapkan E2EE di atasnya.

Memilih setiap layer secara sengaja

Untuk sistem event-driven yang kecil, MQTT dapat mengurangi banyak pekerjaan protokol custom. Topic, subscription, session behavior, keep-alive handling, dan QoS sudah dispesifikasikan. Itu bernilai ketika semantiknya sesuai dengan produk.

QUIC menjadi relevan ketika properti transport itu sendiri penting: beberapa stream independen, setup connection yang lebih cepat pada kondisi yang mendukung, serta ketahanan terhadap sebagian perubahan network path. QUIC tidak menyediakan topic chat, inbox semantics, read receipt, kebijakan offline message, atau conversation authorization.

Architecture review yang berguna memisahkan pertanyaannya:

application:
  Apa yang disebut message?
  Siapa yang boleh menerimanya?
  Apa arti accepted, delivered, dan read?
  Bagaimana retry didedup?
  Bagaimana E2EE bekerja?

messaging protocol:
  topic atau destination eksplisit?
  subscription?
  session state?
  protocol acknowledgement?

transport:
  TCP + TLS?
  QUIC?
  berapa banyak stream?
  bagaimana perilaku reconnect dan migration?

storage:
  offline message?
  ordering?
  retention?
  idempotency?

Setelah boundary tersebut eksplisit, MQTT dan QUIC tidak lagi terlihat sebagai dua produk yang saling bersaing. MQTT dapat menyediakan messaging semantics; QUIC dapat menyediakan transport semantics. Sebuah sistem dapat memilih salah satunya, menggabungkan keduanya melalui protocol stack yang sesuai, atau tidak memakai keduanya. Perbandingan yang tepat dimulai dari alternatif pada layer yang sama, lalu menyusun layer yang tersisa secara sengaja.