Kapan microservices layak dibayar dan bagaimana memotongnya dengan benar: prinsip service boundary berbasis domain, komunikasi sinkron vs asinkron, saga pattern untuk transaksi lintas service, serta failure handling — dengan simulasi ekstraksi modul dari modular monolith kita

Setelah di episode 11 kalian merancang performance & scalability — caching berlapis, mitigasi stampede, dan capacity planning flash sale — pada episode ini kita masuk bab yang paling sering diperdebatkan di industri: microservices.
Perhatikan posisi kita: bukan episode 3, melainkan episode 12 — setelah boundary modul (7), data ownership (8), kontrak API (9), security (10), dan scaling design (11). Itu disengaja. Microservices adalah evolusi dari disiplin-disiplin itu, bukan titik awal. Modular monolith kita sengaja dirancang agar ekstraksinya murah; sekarang kita pelajari kapan dan bagaimana mengeksekusinya.
Microservices membayar biaya operasionalnya hanya jika kalian butuh apa yang hanya ia berikan:
| Sinyal Go | Sinyal Not Yet |
|---|---|
| Tim >15 orang, bottleneck koordinasi rilis | 1-2 tim masih nyaman satu repo |
| Modul punya profil scale sangat beda | Semua scale seragam |
| Domain butuh deploy independence nyata | Rilis mingguan cukup |
| Platform engineering siap (CI/CD, tracing, mesh) | Belum ada tim platform |
| Boundary bounded context stabil & teruji | Domain masih bergerak cepat |
Prasyarat teknis minimal — tanpa ini jangan mulai: CI/CD per service otomatis, distributed tracing end-to-end, centralized logging + metrics, on-call rotation matang, dan kontrak antar service dijaga test. Kompleksitas terdistribusi tanpa observability setara menerbangkan pesawat buta.
Important
Ingat pemicu revisi ADR-0002 kita: tim >15 developer atau traffic >5x proyeksi. Simulasi di episode ini mengasumsikan salah satu pemicu tercapai. Ekstraksi adalah keputusan bertahap per-modul — bukan big bang pecah semuanya.
Aturan pemotongan sama persis dengan modul episode 7 — karena service hanyalah modul yang boundary-nya menjadi proses jaringan:
ordering-service valid; database-service dan business-logic-service adalah distributed monolith.Dari lima modul kita, mana yang diekstrak duluan? Analisis profilnya:
catalog : read-heavy, cache-friendly → TETAP di monolith
inventory : hot saat flash sale, write-heavy,
scaling profile beda jauh → EKSTRAK #1
payment : compliance PCI, isolasi audit,
rilis siklus sendiri → EKSTRAK #2
shipping : integrasi kurir eksternal, latensi tak menentu
→ kandidat ketiga, belum mendesak
ordering : jantung transaksi, butuh ACID lokal
→ tetap inti monolith (sekarang)Inventory dipilih pertama karena mismatch scaling-nya paling tajam: seluruh aplikasi tidak perlu di-scale 10x hanya demi reservasi stok.
Setiap panggilan jaringan bisa gagal tiga cara (timeout, error, sukses-tapi-respon-hilang). Pilih gaya komunikasi secara sadar per aliran:
| Gaya | Cocok Untuk | Harga |
|---|---|---|
| Sync REST/gRPC | Butuh jawaban sekarang (validasi, query) | Coupling availability & latency |
| Async event | Side-effect, fan-out, integrasi | Final consistency, tracing lebih sulit |
Prinsip komposisinya sama dengan episode 8: sinkron hanya di jalur yang menuntut jawaban; sisanya event. Aturan praktis tambahan lintas service:
Tanpa database bersama, tidak ada commit dua fase yang pragmatis. Saga mengganti satu transaksi terdistribusi dengan rangkaian transaksi lokal + aksi kompensasi bila ada yang gagal.
Alur order studi kasus kita sebagai saga orchestration:
Dua gaya koordinasi:
Heuristik pemilihan: choreography untuk rantai pendek sederhana, orchestration begitu ada percabangan kondisi dan kompensasi — persis kasus checkout kita.
Kunci implementasi yang membuat saga benar:
PENDING_STOCK, CHARGING, COMPENSATING), sehingga crash di tengah bisa dilanjutkan, bukan hilang.Failure adalah mode operasi normal terdistribusi, bukan pengecualian:
Timeout : batas tunggu eksplisit < budget caller
Retry : idempotent + backoff + jitter, max 2-3 attempt
Circuit breaker : putus sirkuit saat error rate tinggi,
coba lagi setelah half-open window
Fallback : jawaban cadangan (cached value, degraded mode)
Bulkhead : pisahkan pool resource per dependensiDetail tuning masing-masing pola ini — threshold breaker, jitter distribution, bulkhead sizing — kita kerjakan utuh di episode 16 tentang resilience. Di sini yang penting kesadarannya: tanpa kelima perlengkapan itu, satu service lambat akan meruntuhkan grafik panggilan seluruhnya.
Di monolith, satu stack trace menjawab segalanya. Di services, satu request menyusuri banyak process — tanpa instrumen, kalian buta:
Tip
Sebelum mengekstrak service pertama, pasang OpenTelemetry di monolith dan biasakan tim membaca trace lintas modul. Skill debugging-trace harus sudah otomatis sebelum jarak antar komponen melebar menjadi jaringan.
Inti yang harus dibawa pulang:
Di episode 13 selanjutnya kita perdalam sisi async: event-driven architecture — Kafka secara konsep, delivery semantics, consumer group, event sourcing, dan bagaimana topik-topik studi kasus kita dirancang agar replayable. Sampai jumpa!