Benchmark Payment Gateway Bagian 5 : Keputusan Final, dan Kenapa Repo Kafka-nya Tetap Kami Pertahankan
Seri ini berawal dari pertanyaan mendasar: untuk payment gateway, apakah lebih tepat menggunakan PostgreSQL konvensional atau pendekatan event-sourced berbekal Kafka? Bagian 1 hingga 4 telah memaparkan pembuktian berbasis data empiris, lengkap dengan lika-liku salah tafsir dan proses koreksinya. Pada bagian penutup ini, mari kita rangkum hasil akhirnya sekaligus mengulas pertanyaan yang tak kalah menarik: jika RDBMS yang terpilih, mengapa repositori berbasis Kafka tersebut tetap dipertahankan?
Rekapitulasi Angka Benchmark
Setelah lingkungan pengujian benar-benar steril (sebagaimana diulas pada Bagian 3) serta kendala transaksi ganda berhasil ditangani dan diverifikasi secara deterministik (Bagian 4), berikut ringkasan data akhir — diuji menggunakan protokol integrasi BSI sesungguhnya dengan peningkatan beban (ramp-up) hingga 2.000 TPS pada spesifikasi mesin yang identik:
| Metrik | RDBMS (PostgreSQL) | Event-Sourced (Kafka) |
|---|---|---|
| Median latency | 1,01 ms | 3,83–4,03 ms |
| p99 latency | 112 ms* | 8,5–10,7 ms |
| Virtual user puncak (dari 2.000) | 288 | 100–150 |
| Audit akurasi | LULUS, 0 ketidaksesuaian | LULUS, 0 ketidaksesuaian |
| Saturasi di bawah beban | Tidak ada | Tidak ada |
*Angka p99 RDBMS pada pengujian ini cenderung fluktuatif karena dieksekusi sebelum sterilisasi lingkungan penguji rampung sepenuhnya. Namun nilai mediannya — yang merupakan indikator lebih stabil — konsisten lebih unggul dibanding arsitektur event-sourced di seluruh siklus pengujian.
Kesimpulan Kapasitas: Kedua arsitektur sanggup menangani beban 2.000 TPS secara optimal tanpa menunjukkan gejala saturasi sumber daya. Penurunan performa pada versi event-sourced di Bagian 3 bersumber dari kontaminasi lingkungan pengujian.
Kesimpulan Integritas Data: Poin ini menyajikan temuan yang paling krusial. Studi ini menemukan kategori masalah yang sama sebanyak dua kali pada dua komponen berbeda di versi event-sourced:
- Perbedaan aturan penutupan tagihan
OPENvsINSTALLMENTantara topologi Kafka Streams dan proyeksi PostgreSQL, yang menyebabkan disinkronisasi data tanpa terdeteksi (Bagian 3). - Adanya dua jalur penulisan independen di
PostgresProjectionSinktanpa mekanisme saling verifikasi, yang mengakibatkan satu transaksi tercatat dua kali dengan status bertentangan (Bagian 4).
Keduanya memiliki pola serupa: keberadaan dua entitas terpisah yang menyimpan state masing-masing terhadap transaksi yang sama, yang sewaktu-waktu bisa berselisih (drift). Perlu diluruskan (lihat Bagian 4 untuk detailnya): ini bukan keterbatasan bawaan yang tidak terhindarkan di Opsi B — celahnya bisa ditutup total dengan transaksi atomic langsung di RocksDB pada request thread, alih-alih pola “validasi lokal, append event, proses belakangan” yang justru membuka jeda tersebut. Bedanya dengan RDBMS bukan soal bisa atau tidak bisa menutup celah ini, tapi soal gratis atau tidak: pada arsitektur RDBMS, jaminan atomic itu datang default lewat satu transaksi ACID tanpa perlu dipikirkan; pada Opsi B, jaminan yang setara harus didesain secara sengaja — dan implementasi pembanding di project ini, pada awalnya, tidak melakukannya.
Keputusan Arsitektur: RDBMS untuk Lingkungan Produksi
Untuk skala kebutuhan institusional (kisaran puluhan hingga ratusan TPS pada beban puncak), pertimbangan awal di Bagian 1 terbukti akurat setelah melalui pengujian riil: PostgreSQL relasional dipilih untuk production. Opsi ini menawarkan latency yang lebih rendah, kompleksitas operasional yang minimal (tanpa perlu mengelola kluster Kafka), serta bebas dari risiko disinkronisasi data antar-komponen.
Lalu, Kapan Arsitektur Kafka Tepat Digunakan?
Penting digarisbawahi: kesimpulan di atas berlaku untuk beban kerja dan domain spesifik ini, bukan vonis bahwa event sourcing/Kafka selalu berlebihan. Ada beberapa kondisi di mana neraca trade-off-nya justru berbalik:
- Ada banyak konsumen independen atas event yang sama. Nilai inti CQRS/event sourcing adalah satu event, banyak reaksi — deteksi fraud, poin loyalitas, notifikasi, dashboard real-time, sistem akuntansi, semua membaca stream yang sama secara independen. Di project ini, konsumennya cuma satu (projection sink ke PostgreSQL), jadi keunggulan pub-sub Kafka sama sekali tidak termanfaatkan. Kalau ada lima sistem berbeda yang harus bereaksi terhadap satu pembayaran, hitungannya bisa sangat berbeda.
- Throughput yang sungguh-sungguh tinggi dan sustained, bukan cuma puncak sesaat. Puluhan ribu TPS yang bertahan lama, bukan lonjakan singkat di jam sibuk, mulai mendekati titik di mana single-writer per baris pada RDBMS jadi bottleneck sungguhan, dan partition key sharding ala Kafka Streams punya jalur scale out yang sulit disamai RDBMS. Ini bukan kebetulan, tapi konsekuensi desain sejak awal: RDBMS tradisional dirancang untuk scale up — tambah CPU, RAM, dan disk pada satu mesin yang sama — karena itulah cara paling langsung menjaga jaminan ACID pada satu source of truth. Scale out (menambah mesin, bukan memperbesar mesin yang ada) berarti keluar dari model itu, dan RDBMS baru bisa mengejarnya lewat solusi tambahan seperti sharding di level aplikasi atau tooling pihak ketiga (Citus, Vitess, dan sejenisnya) yang notabene menambah kompleksitas sendiri. Kafka, sebaliknya, memang dirancang scale out sejak awal — partition bisa disebar ke banyak broker, dan menambah kapasitas cukup dengan menambah partition serta broker, tanpa mengorbankan model konsistensinya.
- Event log itu sendiri adalah kebutuhan bisnis atau regulasi, bukan sekadar detail implementasi. Beberapa domain (misalnya core banking atau trading system tertentu) memang menjadikan history event yang bisa di-replay sebagai fitur inti dari aplikasinya, bukan cuma audit trail tempelan di atas RDBMS.
Kalau salah satu dari kondisi di atas benar-benar berlaku, kesimpulan Bagian 1 tentang trade-off Opsi A vs Opsi B bisa berubah total. Yang tidak boleh berubah adalah caranya : dibuktikan dengan data yang benar-benar diukur, bukan dipilih karena kedengarannya lebih modern.
Satu hal perlu diluruskan supaya tidak salah dibaca sebagai kondisi keempat di atas: race condition di Bagian 4 bukan alasan untuk menghindari Kafka. Itu murni soal desain awal yang keliru: implementasi pembanding ini pada mulanya memilih pola validasi lokal lalu proses belakangan, dan pola itulah yang berujung pada bug pembayaran ganda tadi. Bug itu yang mendorong rearsitektur ke satu transaksi RocksDB atomic langsung di request thread (Bagian 6), sehingga Kafka kemudian cuma difungsikan untuk mengirim hasil akhir ke downstream, tidak lagi ikut serta melakukan perhitungan payment.
Ini juga menunjukkan bahwa mendesain aplikasi dengan Kafka membutuhkan lebih banyak pertimbangan. Dengan RDBMS, kita bisa langsung menggunakan SELECT FOR UPDATE tanpa banyak pertimbangan. Sedangkan dengan Kafka, selain menulis query, kita harus berpikir ekstra untuk menentukan key yang tepat, jumlah partisi yang tepat, dan berapa latency antar node — termasuk memastikan satu tagihan (beserta seluruh VA saudaranya) selalu berada di partition yang sama, dan memakai queryMetadataForKey() bawaan Kafka Streams untuk meneruskan request ke instance yang tepat saat scale out.
Mengapa Repositori Kafka Tetap Dipertahankan?
Ini merupakan pertimbangan strategis di luar teknis. Setelah pengujian usai, muncul pemikiran: dari sudut pandang repositori publik dan portofolio ArtiVisi, apakah arsitektur event-sourced berbekal Kafka terasa lebih “menjanjikan” untuk dipresentasikan? Teknologi tersebut kerap dianggap lebih modern dibanding RDBMS relasional biasa.
Namun setelah direfleksikan kembali, kesimpulan yang rasional justru sebaliknya. Penerapan event sourcing dan Kafka mungkin menjadi penanda “tim teknis modern” pada era 2015–2020. Di masa kini, stack tersebut merupakan standar enterprise biasa. Bahkan, menerapkannya di lingkungan produksi untuk skala beban kerja yang tidak membutuhkan spesifikasi tersebut justru berisiko dipersepsikan sebagai over-engineering.
Nilai terpenting dari eksperimen ini adalah pengambilan keputusan arsitektur berbasis data empiris. Narasi tentang pengujian objektif dan evaluasi terbuka jauh lebih kredibel bagi praktisi teknis.
Mengadopsi teknologi baru semata-mata demi citra dapat mengalihkan pilihan pemasaran menjadi risiko operasional di lingkungan produksi. Cacat pembayaran ganda di Bagian 4 berhasil teridentifikasi hanya karena pengujian dilakukan secara sangat mendalam. Pada kondisi operasional biasa, celah semacam itu berpotensi lolos dan berdampak langsung pada pengguna akhir. Kondisi tersebut tentu jauh lebih merugikan bagi reputasi dibanding memilih sistem RDBMS konvensional yang terbukti andal.
Oleh karena itu, pembagian peran repositori ditetapkan sebagai berikut:
payment-gateway(RDBMS): Difungsikan untuk lingkungan produksi.payment-gateway-evtsrc(Kafka + RocksDB + CQRS): Tetap dipublikasikan di GitHub sebagai bukti kapabilitas teknis, referensi arsitektur, dan bahan studi kasus.
Penggunaan RDBMS di lingkungan produksi didasari oleh data empiris yang paling sesuai dengan karakteristik beban kerja. Repositori Kafka yang dibangun secara terpisah menjadi bukti bahwa pilihan ini diambil murni berdasarkan pertimbangan teknis.
Penutup
Benang merah utama dari seluruh rangkaian pengujian ini adalah: data yang tampak rapi dan tes yang berstatus hijau merupakan hal mendasar, namun belum cukup. Setiap hasil perlu diverifikasi, diaudit ulang, dan dikaji secara kritis — bahkan ketika proses pembangunannya dibantu oleh AI. Sepanjang proyek ini, Claude Code mengidentifikasi kekeliruan benchmark awal dari agent lain, sekaligus mengoreksi kesimpulan ralatnya sendiri yang sempat berlebihan. Kedua hal tersebut terungkap karena adanya proses verifikasi ulang yang teliti.
Bagi rekan-rekan yang ingin mempelajari rincian teknisnya lebih lanjut, seluruh kode program, panduan remediation, data mentah benchmark, dan laporan analisis tersedia pada kedua repositori publik di atas dengan lisensi Apache 2.0.
Ada satu babak tambahan yang tidak direncanakan sejak awal. Proses menulis dan meninjau ulang seri ini sendiri — khususnya bagian soal detect-and-flag di atas — memicu pertanyaan yang membongkar celah desain lain, lebih dalam dari yang dibahas di Bagian 4. Bagian 6 menceritakan bagaimana itu ditemukan, apa yang dibongkar dan dibangun ulang, dan angka benchmark setelahnya.
Terima kasih telah menyimak seri ini sejauh ini. Semoga bermanfaat — dan ternyata belum benar-benar selesai.