
Alasan mengapa semakin lama menulis kode, saya semakin menghindari teknologi yang mengejar performa ekstrem atau tren semata, dan lebih memilih arsitektur dengan total friksi paling rendah.
Waktu awal-awal getol ngoding, gw gampang banget tergiur sama apa pun yang lagi ramai di linimasa. Ada framework baru dengan klaim "100x faster than Node", bawaannya pengen langsung rewrite. Liat postingan arsitektur berlapis-lapis lengkap dengan diagram kotak-kotak rapi, gw langsung merasa kode gw amatir kalau ga menerapkan struktur yang sama.
Lalu realita produksi masuk.
Setelah beberapa kali dibangunin jam 2 pagi karena service macet, pusing menelusuri delapan lapis interface kosong cuma buat nemu satu query SQL, atau menunggu proses build yang lama hanya demi memperbaiki typo satu baris, cara pandang gw bergeser total.
Sekarang patokan gw sederhana: cari teknologi yang trade-off keseluruhannya paling kecil untuk problem yang lagi diselesaikan, bukan yang paling ekstrem di satu sisi.
Di lapangan, pilihan stack sering kali ditarik ke salah satu dari tiga sudut ini:
Niatnya bagus: mengejar binary kecil dan pemakaian RAM di bawah 10MB dengan menulis semua hal pakai Rust atau C++.
Bukan berarti gw anti-Rust atau benci bahasa tingkat rendah. Rust, C++, atau Zig itu luar biasa kalau ditempatkan di porsinya: bikin core runtime engine, database storage engine, codec video/audio, atau driver sistem operasi. Tapi kalau dipakai buat bangun aplikasi normal sehari-hari, automasi, atau backend bisnis, trade-off waktu development dan mental overhead-nya sering kali ga sebanding.
Menambah satu field di payload JSON butuh waktu lebih lama karena harus berurusan dengan compile-time checks yang ketat. Proses kompilasi dan build lambat. Energi yang harusnya dipakai buat menyelesaikan logika produk malah habis buat mengurus ritual bahasa.
Sudut ini biasanya diisi oleh proyek yang arsitekturnya disusun berdasarkan apa yang sedang populer bulan ini.
User aktif belum sampai seratus, tapi penyimpanan sudah dipecah ke lima tempat: database relasional, vector database khusus, document store, cache layer, dan time-series database. Semuanya dipasang di cluster Kubernetes multi-node.
Kelihatannya canggih di atas kertas. Tapi begitu masuk operasional, pemeliharaannya jadi mimpi buruk. Begitu ada network partition di server atau koneksi drop di homelab, waktu lu habis buat memastikan data antar-database tidak keluar jalur. Saat ada request gagal di tengah jalan, mencari titik putusnya butuh investigasi berbelit-belit.
Ini kebiasaan membungkus kode sederhana ke dalam lapisan abstraksi yang berlebihan demi mengikuti pola Clean Architecture secara tekstual.
Untuk fungsi sesederhana mengambil data user berdasarkan ID, alurnya harus melewati Controller, Presenter, UseCaseInterface, UseCaseImpl, RepositoryInterface, RepositoryImpl, DTO, dan Mapper.
Kodenya rapi secara teori, tapi sulit dinavigasi. Saat ada bug, kita harus klik berkali-kali melewati interface yang isinya cuma melempar parameter ke file berikutnya. Stack trace saat error jadi panjang dan penuh wrapper yang tidak memberi informasi baru.
Setelah beberapa kali terjebak di pola-pola tadi, gw lebih memilih opsi yang memberikan efisiensi cukup tanpa menambah kerumitan operasional.
Beberapa keputusan di proyek belakangan ini (termasuk saat menyusun runtime agent):
Makin lama berkutat dengan sistem yang harus jalan terus-menerus, semakin kita menghargai kesederhanaan.
Bahasa low-level punya tempatnya sendiri sebagai fondasi engine di balik layar. Namun untuk aplikasi di atasnya, kode yang baik adalah kode yang selesai sesuai kebutuhan, gampang dipahami orang lain (atau diri sendiri beberapa bulan ke depan), dan jarang bikin panik saat ditinggal tidur.