Retrospektif mingguan untuk menilai trade-off arsitektur adalah cara sederhana agar tim engineering tidak membuat keputusan arsitektur berdasarkan tren, tekanan sesaat, atau asumsi yang belum terukur. Dalam weekly retro atau sprint review, tim bisa memakai kerangka evaluasi yang konsisten untuk menilai apakah masalah minggu ini memang membutuhkan pemecahan service, peningkatan scaling, atau justru cukup diselesaikan di monolith modular.
Intinya bukan mencari arsitektur paling modern, tetapi memilih biaya kompleksitas yang sebanding dengan masalah yang benar-benar terjadi. Jika bottleneck masih lokal, observability masih terbatas, dan koordinasi tim belum siap, memecah sistem terlalu cepat justru menambah risiko deployment, debugging, dan ownership. Sebaliknya, jika domain mulai saling mengganggu, deployment sering saling blokir, dan kebutuhan scaling benar-benar berbeda, pemisahan service bisa masuk akal.
Tujuan retrospektif mingguan untuk evaluasi arsitektur
Banyak tim melakukan retro mingguan hanya untuk membahas hal seperti incident, velocity, atau hambatan koordinasi. Itu berguna, tetapi kurang lengkap jika keputusan teknis besar tidak ikut direview. Padahal, banyak keputusan arsitektur lahir secara bertahap: menambah queue, memisahkan database, membuat worker terpisah, atau mengubah satu modul menjadi service mandiri.
Retrospektif arsitektur mingguan bertujuan untuk menjawab pertanyaan berikut:
- Masalah apa yang benar-benar muncul minggu ini? Misalnya deploy lambat, query berat, lonjakan traffic, retry job yang gagal, atau satu modul membuat modul lain sulit diubah.
- Apakah masalahnya bersifat lokal atau sistemik? Jika lokal, perbaikan pada modul, cache, indexing, atau queue mungkin cukup.
- Apakah solusi yang diusulkan menambah kompleksitas operasional? Setiap service baru menambah monitoring, deployment, alerting, tracing, dan potensi kegagalan jaringan.
- Apakah tim siap mengoperasikan arsitektur baru? Arsitektur bukan hanya desain kode. Ia juga mencakup incident response, on-call, debugging, rollback, dan ownership lintas tim.
Prinsip praktis: jangan naik tingkat arsitektur sebelum bukti masalahnya lebih mahal daripada biaya kompleksitas solusi.
Tiga keputusan inti yang perlu direview setiap minggu
1. Kapan tetap di monolith modular
Monolith modular sering menjadi pilihan paling efisien untuk banyak tim, terutama ketika domain masih berkembang cepat, ukuran tim belum besar, dan kebutuhan scaling belum sangat berbeda antar fitur.
Pertahankan monolith modular jika kondisi berikut masih berlaku:
- Bottleneck performa berasal dari beberapa endpoint, query, atau job tertentu, bukan seluruh aplikasi.
- Boundary domain sudah bisa dipisahkan di level modul, package internal, atau folder ownership tanpa harus jadi service terpisah.
- Deployment aplikasi masih bisa dilakukan dengan risiko yang dapat diterima.
- Tim masih lebih cepat bergerak dengan satu repository, satu pipeline, dan satu cara observability.
- Masalah utama adalah kualitas desain internal: dependency antar modul kabur, testing lemah, atau query belum optimal.
Monolith modular bekerja baik karena komunikasi antar modul tetap in-process. Tidak ada latensi jaringan, tidak ada kegagalan karena timeout antar service, dan transaksi data lebih sederhana dikelola. Selain itu, pengujian integrasi biasanya lebih mudah dilakukan.
Namun, monolith modular tetap menuntut disiplin. Jika semua modul saling mengakses tabel dan fungsi internal tanpa batas, hasilnya adalah monolith yang sulit diubah. Jadi, keputusan untuk tetap di monolith hanya masuk akal bila tim juga memperbaiki batas modul, kontrak internal, dan pengujian.
2. Kapan memecah ke service
Pemisahan ke service layak dipertimbangkan ketika pemisahan itu menyelesaikan masalah yang jelas, bukan sekadar memenuhi preferensi desain. Beberapa sinyal yang lebih valid:
- Satu domain memiliki pola scaling yang sangat berbeda, misalnya proses media, pencarian, atau notifikasi berat.
- Perubahan di satu area sering memblokir deploy area lain.
- Kebutuhan reliabilitas dan lifecycle operasional antar domain berbeda jauh.
- Satu komponen membutuhkan teknologi, storage, atau model eksekusi yang berbeda secara signifikan.
- Ownership tim sudah cukup jelas sehingga service baru tidak menjadi area tanpa penanggung jawab.
Contoh yang sering valid: sistem checkout utama tetap di monolith modular, tetapi pengiriman email massal, rendering dokumen, atau indexing search dipisah menjadi worker/service terkelola karena pola beban dan failure mode-nya berbeda.
Yang perlu dipahami: memecah ke service tidak hanya memindahkan kode. Tim juga memindahkan batas tanggung jawab menjadi kontrak jaringan. Akibatnya:
- Debugging berubah dari membaca stack trace lokal menjadi menganalisis log lintas service.
- Komunikasi sinkron menambah risiko timeout, retry storm, dan partial failure.
- Perubahan skema data tidak lagi bisa diasumsikan atomik di semua komponen.
- Testing menjadi lebih kompleks karena melibatkan contract test, environment integration, dan stub/mocking yang lebih banyak.
3. Kapan menunda scaling
Sering kali keputusan terbaik adalah tidak melakukan perubahan arsitektur besar minggu ini. Menunda scaling bukan berarti mengabaikan masalah, tetapi memastikan tim menyelesaikan bottleneck nyata dengan biaya paling rendah terlebih dahulu.
Tunda scaling besar jika:
- Belum ada metrik yang menunjukkan bottleneck konsisten.
- Lonjakan traffic masih temporer dan bisa ditangani dengan caching, queue, rate limit, atau tuning database.
- Incident lebih banyak disebabkan bug logika, query buruk, atau deployment yang belum stabil.
- Tim belum punya observability yang cukup untuk mengukur dampak perubahan.
Kesalahan umum adalah menganggap kenaikan traffic otomatis berarti harus microservices. Padahal banyak sistem bisa bertahan cukup lama dengan pendekatan yang lebih sederhana: optimasi query, background processing, cache, connection pooling, read replica bila memang diperlukan, atau pemisahan workload secara internal dulu.
Trade-off yang harus dibahas dalam weekly retro
Biaya operasional
Setiap service baru menambah unit operasional baru. Artinya ada pipeline build, deployment, secret management, konfigurasi environment, dashboard monitoring, alert, dan prosedur rollback tersendiri.
Pertanyaan retro:
- Berapa banyak pekerjaan operasional tambahan jika modul ini jadi service?
- Siapa yang akan on-call?
- Apakah tim platform atau DevOps siap mendukungnya?
- Apakah service baru akan punya database sendiri? Jika ya, bagaimana backup dan migration-nya?
Kompleksitas observability
Dalam monolith, satu request biasanya lebih mudah diikuti. Pada arsitektur service, satu request pengguna bisa melewati API gateway, service utama, queue, worker, lalu database atau storage lain. Tanpa tracing dan correlation ID yang konsisten, debugging akan melambat drastis.
Hal yang perlu direview:
- Apakah log sudah punya correlation ID?
- Apakah metric utama per domain sudah ada: latency, error rate, throughput, queue depth?
- Apakah tim bisa membedakan bottleneck CPU, I/O, database, atau dependency eksternal?
Beban deployment
Pemisahan service dapat mengurangi risiko deploy besar jika boundary memang jelas. Namun jika boundary belum matang, hasilnya justru banyak deploy kecil yang saling tergantung. Ini bisa memperbesar koordinasi, versioning, dan risiko kompatibilitas kontrak.
Tanyakan dalam retro:
- Apakah deploy sering gagal karena perubahan lintas modul?
- Apakah satu tim harus menunggu tim lain untuk rilis perubahan kecil?
- Apakah kontrak API antar komponen sudah stabil?
Risiko koordinasi tim
Arsitektur memengaruhi struktur komunikasi tim. Service yang dipisah tanpa ownership yang jelas akan menciptakan area abu-abu: bug dilempar ke tim lain, perubahan kecil memerlukan sinkronisasi panjang, dan incident response menjadi lambat.
Evaluasi:
- Apakah ada pemilik domain yang jelas?
- Apakah perubahan lintas domain sering tertunda karena antrean review atau approval?
- Apakah pemisahan service akan mengurangi atau justru menambah dependency antartim?
Dampak maintainability
Maintainability bukan hanya soal ukuran codebase. Sistem dianggap lebih mudah dirawat jika perubahan lokal tidak menimbulkan efek samping besar, pengujian masuk akal, dan batas domain mudah dipahami. Service terpisah bisa meningkatkan maintainability bila boundary benar-benar sesuai domain. Tetapi jika domain masih cair, pemisahan terlalu dini akan menghasilkan kontrak yang cepat usang dan duplikasi logika di banyak tempat.
Checklist retrospektif mingguan
Checklist berikut dapat dipakai langsung saat sprint review atau weekly retro. Fokusnya adalah keputusan minggu ini, bukan debat arsitektur abstrak.
Checklist masalah dan bukti
- Masalah arsitektur apa yang benar-benar muncul minggu ini?
- Apa buktinya: latency naik, error rate naik, queue menumpuk, deploy saling blokir, atau query timeout?
- Apakah masalahnya berulang minimal beberapa kali, atau hanya satu kejadian insidental?
- Apakah bottleneck sudah terlokalisasi pada modul, endpoint, job, atau dependency tertentu?
Checklist opsi solusi
- Bisakah masalah diselesaikan tanpa memecah service: indexing, caching, batching, queue, refactor modul, atau isolasi proses worker?
- Jika ingin memecah service, apa boundary domain yang jelas?
- Data apa yang harus dipisah, dibagikan, atau direplikasi?
- Apakah komunikasi sinkron benar-benar dibutuhkan, atau event/asynchronous lebih aman?
Checklist kesiapan operasional
- Apakah dashboard, logging, tracing, dan alert untuk komponen baru sudah direncanakan?
- Apakah ada runbook incident dan rollback?
- Apakah pipeline CI/CD siap menangani service tambahan?
- Apakah tim paham failure mode baru seperti timeout, retry, duplicate event, dan eventual consistency?
Checklist dampak tim
- Siapa owner teknis dari perubahan ini?
- Apakah perubahan ini mengurangi beban koordinasi atau menambahnya?
- Apakah tim yang menerima ownership punya kapasitas maintenance jangka panjang?
Matriks keputusan sederhana
Gunakan matriks berikut untuk memutuskan langkah minggu ini.
| Kondisi | Pilihan yang lebih masuk akal | Alasan |
|---|---|---|
| Bottleneck masih lokal, domain belum stabil, observability terbatas | Tetap di monolith modular | Kompleksitas tambahan belum sebanding dengan manfaat |
| Workload tertentu jauh lebih berat atau berbeda pola eksekusinya | Pisahkan worker atau service khusus | Scaling dan isolasi failure lebih terarah |
| Deployment lintas domain sering saling memblokir dan ownership sudah jelas | Pertimbangkan pemisahan service | Boundary organisasi dan teknis mulai selaras |
| Traffic naik tetapi masalah utama belum terukur dengan baik | Tunda scaling besar, ukur lebih dulu | Mencegah over-engineering berbasis asumsi |
| Masalah utama ada pada query, cache, atau background processing | Optimasi internal dulu | Biasanya lebih murah dan cepat daripada migrasi arsitektur |
Jika tool atau template retro Anda tidak mendukung tabel, ubah menjadi tiga kolom sederhana di dokumen review: sinyal, opsi, biaya kompleksitas.
Contoh skenario: traffic produk naik minggu ini
Misalkan sebuah produk SaaS B2B mengalami kenaikan traffic setelah peluncuran integrasi baru. Dalam seminggu terakhir, tim melihat:
- Endpoint pembuatan laporan melambat pada jam sibuk.
- Queue notifikasi tertunda karena worker berbagi resource dengan request utama.
- Deploy fitur billing ikut tertunda karena ada perubahan besar pada modul laporan.
Tim lalu membahas tiga opsi dalam retrospektif.
Opsi A: langsung memecah aplikasi menjadi beberapa microservice
Ini terdengar menarik, tetapi terlalu besar untuk masalah yang baru teridentifikasi seminggu. Risiko langsungnya:
- Boundary domain belum matang.
- Observability lintas service belum siap.
- Tim akan menghabiskan waktu di network contract, deployment, dan sinkronisasi data.
Keputusan ini biasanya buruk jika motivasinya hanya karena traffic naik.
Opsi B: tetap monolith modular, tetapi memisahkan workload laporan dan notifikasi
Ini sering menjadi langkah transisi yang lebih aman:
- Modul laporan dirapikan boundary-nya di dalam monolith.
- Proses generate laporan dipindahkan ke job asynchronous agar request utama tidak menunggu terlalu lama.
- Worker notifikasi dijalankan terpisah dari web process agar kompetisi resource berkurang.
- Tambahkan metric queue depth, durasi job, dan latency endpoint laporan.
Pendekatan ini menyelesaikan bottleneck paling nyata tanpa memecah seluruh sistem.
Opsi C: memecah hanya komponen laporan menjadi service terpisah
Ini masuk akal jika setelah beberapa minggu terbukti bahwa:
- Workload laporan membutuhkan scaling yang benar-benar berbeda.
- Dependensi library atau storage untuk laporan berbeda signifikan dari aplikasi utama.
- Ownership tim laporan sudah jelas.
- Kontrak input-output laporan cukup stabil.
Dalam situasi ini, pemisahan terbatas lebih sehat daripada migrasi besar sekaligus.
Hasil keputusan retro yang baik
Contoh keputusan yang matang untuk minggu itu bisa berbunyi seperti ini:
Minggu ini kami tidak memecah monolith menjadi microservices. Kami akan mengisolasi generate laporan ke background job, memisahkan worker notifikasi dari process web, menambah metric pada queue dan endpoint laporan, lalu mengevaluasi ulang dua minggu lagi. Pemisahan service baru dipertimbangkan jika bottleneck tetap ada dan ownership domain laporan stabil.
Keputusan seperti ini lebih berguna daripada pernyataan abstrak seperti “kita perlu arsitektur yang lebih scalable”.
Template notulen retrospektif arsitektur
Berikut format ringkas yang bisa dipakai tim setiap minggu:
Minggu ini kami melihat masalah berikut:
- [masalah utama]
- [indikator/metric]
- [dampak ke user atau tim]
Bottleneck terlokalisasi di:
- [modul/endpoint/job/dependency]
Opsi yang dievaluasi:
1. [optimasi internal]
2. [isolasi workload]
3. [pecah ke service]
Trade-off utama:
- Operasional: [rendah/sedang/tinggi]
- Observability: [siap/belum siap]
- Deployment: [lebih sederhana/lebih kompleks]
- Koordinasi tim: [berkurang/bertambah]
- Maintainability: [membaik/memburuk/netral]
Keputusan minggu ini:
- [pilihan]
- [alasan]
- [indikator yang akan dipantau sampai retro berikutnya]
Template ini memaksa tim untuk mengaitkan keputusan dengan bukti, bukan preferensi personal.
Anti-pattern yang perlu dihindari
Mengejar arsitektur “keren” tanpa kebutuhan nyata
Anti-pattern paling umum adalah mengadopsi microservices, event-driven, atau pemisahan database hanya karena dianggap lebih profesional. Tanpa masalah yang tepat, hasilnya adalah biaya operasional naik tanpa perbaikan yang berarti.
Menggunakan traffic sebagai satu-satunya alasan
Traffic tinggi tidak otomatis berarti arsitektur harus dipecah. Yang perlu dilihat adalah karakter bottleneck: CPU, database, I/O, lock contention, external API, atau proses background. Solusi yang benar bergantung pada sumber masalah, bukan pada angka traffic semata.
Memecah service sebelum boundary domain jelas
Jika tim belum bisa mendefinisikan dengan jelas data, tanggung jawab, dan kontrak domain, service baru hanya memindahkan kekacauan internal menjadi kekacauan jaringan.
Melupakan biaya observability
Tim sering menghitung effort coding, tetapi lupa bahwa log, metric, trace, dashboard, dan alert adalah bagian dari arsitektur. Tanpa itu, incident di arsitektur terdistribusi akan lebih mahal ditangani.
Menganggap scaling sebagai proyek satu arah
Tidak semua masalah butuh perubahan permanen. Kadang yang dibutuhkan hanya isolasi worker, tuning database, atau pengendalian beban sementara. Jika retro mingguan dilakukan disiplin, tim bisa menghindari keputusan besar yang sebenarnya belum perlu.
Langkah praktis untuk diterapkan mulai minggu ini
- Tambahkan satu segmen khusus arsitektur di weekly retro, durasi 10-15 menit.
- Batasi diskusi pada masalah yang benar-benar terjadi minggu ini, lengkap dengan metric atau bukti teknis.
- Paksa tim membandingkan minimal tiga opsi: tetap di monolith modular, isolasi workload, atau pecah ke service.
- Nilai setiap opsi dengan lima dimensi: operasional, observability, deployment, koordinasi tim, maintainability.
- Tentukan indikator evaluasi untuk minggu berikutnya, misalnya latency endpoint, queue depth, lead time deploy, atau jumlah incident.
- Catat keputusan yang sengaja ditunda agar penundaan bersifat terukur, bukan mengambang.
Dengan pola ini, retrospektif mingguan untuk menilai trade-off arsitektur menjadi alat pengambilan keputusan yang konkret. Tim tidak terjebak antara dua ekstrem: mempertahankan monolith yang sudah jelas bermasalah, atau memecah sistem terlalu dini. Yang dicari adalah keputusan paling masuk akal untuk kondisi minggu ini, dengan biaya kompleksitas yang bisa dipertanggungjawabkan.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!