Benchmark Payment Gateway Bagian 3 : Ketika Benchmark Menipu Diri Sendiri
Di Bagian 2, indikator benchmark yang bermasalah telah dibongkar dan diperbaiki. Kini saatnya mengeksekusi pengujian yang sesungguhnya. Bagian ini menyajikan dinamika yang cukup emosional: mulai dari ditemukannya bug domain penting berkat komparasi dua versi sistem, hingga fenomena benchmark dramatis yang ternyata dipicu oleh kesibukan internal komputer penguji.
Bug Pertama: Terdeteksi Melalui Komparasi Dua Sistem
Pengujian valid pertama menunjukkan anomali tajam: arsitektur event-sourced hanya berhasil menerima 209 pembayaran, sedangkan arsitektur RDBMS sanggup memproses 28.953 pembayaran dengan traffic yang persis sama.
Penyelidikan mendalam menemukan akar masalahnya pada dokumentasi CLAUDE.md yang menjadi rujukan kedua proyek. Dokumen tersebut keliru menyatukan aturan penutupan untuk dua tipe tagihan berbeda, yaitu OPEN dan INSTALLMENT. Aturan yang benar adalah:
INSTALLMENT: Tagihan skema cicilan yang memiliki batas nominal dan otomatis ditutup begitu lunas.OPEN: Tagihan rekening aktif secara terus-menerus (seperti VA donasi) yang tidak pernah ditutup secara otomatis meski dibayar berulang kali.
Implementasi event-sourced secara patuh mengikuti dokumentasi yang keliru tersebut, sehingga tagihan bertipe OPEN langsung dikunci saat mencapai akumulasi nominal tertentu — bertindak layaknya INSTALLMENT. Akibatnya, seluruh transaksi susulan ditolak otomatis dan angka penerimaannya anjlok dibanding versi RDBMS yang sejak awal mengacu pada logika yang tepat.
Hal menarik dari insiden ini adalah mekanisme terungkapnya masalah. Masing-masing implementasi RDBMS dan event-sourced sebenarnya lulus di seluruh unit test internalnya. Kekeliruan pemahaman domain pada dokumen rujukan baru terdeteksi saat dua sistem independen ini diuji berdampingan dan menghasilkan keluaran yang jauh berbeda. Pengujian pada satu sistem saja — betapa pun komprehensif test suite-nya — tak akan sanggup menangkap kekeliruan ini sebab pengujian itu sendiri dirancang di atas asumsi keliru yang sama.
Temuan Kedua: Lonjakan Lock Contention pada RDBMS
Setelah bug domain tersebut diperbaiki, giliran versi RDBMS yang menunjukkan dinamika tak terduga. Pada dua eksekusi beruntun tanpa mengosongkan database, eksekusi pertama berjalan mulus (p99 21ms), sedangkan eksekusi kedua mengalami penurunan performa signifikan (p99 melonjak ke 471ms dan memerlukan 662 virtual user dibanding 26 pada eksekusi pertama).
Dugaan awal mengarah pada rebutan resource laptop antar-sistem. Namun setelah seluruh layanan event-sourced dihentikan total dan RDBMS diuji secara terisolasi, gejala penurunan tetap terjadi. Penyebab sesungguhnya terkuak melalui penelusuran query database:
SELECT id_charge, count(*) FROM payment GROUP BY id_charge ORDER BY count(*) DESC;
-- dua tagihan OPEN : masing-masing mengumpulkan 57.781 dan 57.255 baris
-- tagihan lainnya : di bawah 10 baris
Dua tagihan bertipe OPEN (yang tidak pernah ditutup) menyerap hampir seluruh traffic transaksi. Pada eksekusi kedua, kedua tagihan tersebut telah menampung 115.045 baris riwayat pembayaran. Operasi SELECT FOR UPDATE pada PostgreSQL harus mengunci baris dan mengantre di atas tumpukan 115 ribu riwayat data — jauh lebih beban dibanding mengunci baris yang masih bersih.
Evaluasi berbasis rentang waktu (time-window bucket) mengonfirmasi bahwa penurunan performa ini tidak terjadi secara merata. Latency median tetap stabil di setiap fase, tetapi latency p95/p99 pada rentang 1.000→2.000 TPS melonjak drastis. Fenomena ini merupakan karakteristik alami dari pessimistic locking saat menangani traffic tinggi pada entitas data yang sama.
Benchmark Paling Dramatis
Setelah penyesuaian dilakukan, database dibersihkan ulang untuk mendapatkan angka baseline yang murni. Dua percobaan awal sempat gagal — eksekusi pertama dihentikan akibat dugaan interferensi proses latar belakang, sementara eksekusi kedua menghasilkan latency p99 hingga 9,98 detik dengan lonjakan load average komputer dari 2,96 menjadi 7,86.
Penyebabnya teridentifikasi belakangan: OrbStack (runtime Docker yang digunakan) menjalankan VM yang mengalami kondisi hang, ditambah repositori lain yang mengeksekusi container melalui Testcontainers tanpa terdeteksi. Komputer kemudian diuji ulang setelah restart dan pembersihan total container serta volume yang tidak aktif.
Pengujian berikutnya menghasilkan temuan mencolok: arsitektur event-sourced mencatatkan p99 di rentang 1,16–3,22 detik (dibanding RDBMS yang konsisten di bawah 51ms), membutuhkan lebih dari 1.200 virtual user untuk mencapai throughput setara. Pengujian validasi data bahkan mengalami kegagalan dua kali berturut-turut dengan pola konsisten — sebuah bankReference tercatat dua kali, yakni sebagai transaksi berhasil sekaligus transaksi ganda.
Hasil ini mengindikasikan kendala serius pada performa sekaligus integritas transaksi finansial. Dokumentasi dan analisis komprehensif pun disusun untuk merinci temuan ini.
Ternyata Masih Terkecoh
Sebelum analisis tersebut dipublikasikan, pemeriksaan ulang menemukan bahwa sistem komputer masih menjalankan proses yang tidak diinginkan — terdapat sesi terpisah yang mengaktifkan Testcontainers di tengah setup pengujian. Kali ini, pengujian dihentikan sejenak untuk memverifikasi kebersihan lingkungan sistem melalui docker ps -a dan uptime hingga dipastikan bebas dari interferensi.
Hasil eksekusi setelah lingkungan pengujian dipastikan steril menunjukkan kontras yang drastis. Arsitektur event-sourced yang semula dianggap bermasalah ternyata mencatatkan p99 di rentang 8,5–9,4 milidetik — bahkan lebih responsif pada tail latency dibanding RDBMS — serta lulus sempurna pada pengujian validasi data tanpa anomali sedikit pun. Hasil ini terbukti konsisten pada pengujian ulang.
Kesimpulannya menjadi bahan evaluasi mendasar: temuan paling dramatis sepanjang proyek ini rupanya merupakan efek samping dari keterbatasan sumber daya komputer yang terbagi dengan proses lain. Angka yang terukur memang riil pada kondisi tersebut, namun kondisi pengujiannya sendiri terganggu oleh faktor eksternal.
Temuan ini dipublikasikan secara terbuka sebagai ralat. Mengganti angka begitu saja tanpa penjelasan terbuka berisiko menyesatkan pembaca yang mengikuti perkembangan pengujian.
Kondisi ini menegaskan pelajaran penting terkait metodologi pengujian: validitas benchmark sangat bergantung pada kebersihan lingkungan eksekusinya. Sebelum menarik kesimpulan dari sebuah pengukuran performa, kebersihan dan isolasi sistem penguji wajib dipastikan terlebih dahulu.
Kisah ini belum berakhir. Dokumen ralat tersebut rupanya perlu dicermati lebih lanjut — topik yang dibahas pada bagian selanjutnya, berawal dari pertanyaan sederhana: jika lonjakan latency murni disebabkan oleh interferensi lingkungan, bagaimana dengan temuan terkait transaksi ganda?
Stay tuned …