Kriteria & Syarat Pemecahan Service (Microservices Decomposition)
Tujuan dokumen: Menjadi dasar kajian tim teknis untuk menjawab satu pertanyaan untuk setiap kandidat service: “Kenapa bagian ini harus dipisah jadi service sendiri — dan apa yang tidak bisa dilakukan oleh monolith kalau tidak dipisah?”
Output yang diharapkan dari tim: Setiap kandidat service (Product, Order, Payment, dst.) diisi ke dalam Scorecard di Bagian 6, lengkap dengan bukti/argumen, lalu diambil keputusan: Split / Tunda / Jangan Split.
0. Cara Pakai Dokumen Ini
Section titled “0. Cara Pakai Dokumen Ini”- Baca Bagian 1 dulu (prinsip dasar) — ini yang bikin diskusi tidak melebar ke “pokoknya microservices”.
- Untuk tiap kandidat service, jalankan pertanyaan di Bagian 2 (justifikasi) dan cek jebakan di Bagian 3 (anti-pattern).
- Kajian database di Bagian 4 — ini bagian tersulit dan paling sering diremehkan. Jangan dilewati.
- Uji desain dengan fitness function di Bagian 5.
- Isi Scorecard di Bagian 6 per service. Ada aturan skor + hard blocker (veto).
- Bagian 7 = contoh boundary khas ecommerce + contoh 1 scorecard yang sudah diisi, sebagai referensi.
1. Prinsip Dasar (baca ini sebelum berdebat)
Section titled “1. Prinsip Dasar (baca ini sebelum berdebat)”Beban pembuktian ada di pihak yang mau memecah. Default posisi yang sehat: jangan dipecah dulu. Sebuah service baru harus “membayar” kompleksitas yang ia timbulkan (network, konsistensi data, deployment, observability). Kalau tidak ada masalah nyata yang ia selesaikan, dia tidak layak dipecah.
Tiga prinsip pegangan:
- Mulai dari Modular Monolith, bukan Distributed Monolith. Kalau boundary masih cair, rapikan dulu jadi modul-modul dengan batas jelas di dalam satu aplikasi. Refactor batas modul itu murah; refactor batas antar-service itu mahal.
- Pecah sepanjang batas yang (a) tidak butuh transaksi bersama dan (b) tidak sering berubah bersamaan. Kalau dua kandidat selalu berubah bareng atau butuh konsistensi ketat, itu bukti kuat mereka satu service.
- Yang susah bukan memecah kode — tapi memecah data. Lihat Bagian 4.
2. Justifikasi VALID untuk Memisah Service
Section titled “2. Justifikasi VALID untuk Memisah Service”Ubah tiap kriteria jadi pertanyaan yang bisa dijawab konkret. Kandidat yang kuat biasanya lolos di beberapa kriteria, bukan cuma satu.
| # | Kriteria | Pertanyaan uji | Contoh ecommerce yang lolos |
|---|---|---|---|
| J1 | Independent Deployability | Apakah bagian ini perlu rilis di ritme/frekuensi berbeda dari yang lain? Kalau selama ini selalu deploy barengan → sinyal bukan service terpisah. | Product Catalog sering update (harga, deskripsi) tanpa menyentuh logic Payment. |
| J2 | Independent Scalability | Apakah profil bebannya beda (RPS, CPU/IO/memory, pola burst)? | Search & Product = read-heavy dan spike saat campaign; Payment = throughput rendah tapi kritikal. |
| J3 | Fault Isolation (blast radius) | Kalau bagian ini mati, apakah sisanya harus tetap hidup? | Notification/email down → checkout tetap harus jalan. |
| J4 | Team Ownership (Conway’s Law) | Apakah ada tim berbeda yang saling nabrak di kode ini? Batas service mengikuti batas tim. | Tim Payment ≠ tim Catalog; mereka tidak boleh saling blokir rilis. |
| J5 | Technology Divergence | Apakah butuh runtime/stack yang genuinely beda? | Search butuh Elasticsearch/OpenSearch; rekomendasi butuh Python/ML stack. |
| J6 | Bounded Context (DDD) | Apakah ada batas domain jelas: kohesi tinggi di dalam, coupling longgar ke luar? | “Katalog” vs “Pemenuhan Pesanan” adalah dua bahasa/domain berbeda. |
| J7 | Compliance / Security Isolation | Perlu isolasi data, audit scope, atau blast radius kredensial? | Payment perlu isolasi (mis. lingkup PCI-DSS) dari sistem lain. |
| J8 | Independent Lifecycle Data | Apakah datanya punya siklus hidup & pola akses sendiri? | Cart bersifat ephemeral/TTL; Order bersifat permanen & auditable. |
Aturan main: kalau sebuah kandidat hanya lolos 1 kriteria dan itu pun lemah → kemungkinan besar cukup jadi modul, belum perlu jadi service.
3. Anti-Pattern & Alasan yang DITOLAK
Section titled “3. Anti-Pattern & Alasan yang DITOLAK”Ini yang harus “ditembak” di review kalau muncul:
- ❌ “Karena microservices itu modern / best practice.” Hype-driven, bukan alasan teknis.
- ❌ Split per technical layer, bukan per business capability. Jebakan paling umum. Contoh salah: bikin “service validasi”, “service akses DB”, “service khusus REST”. Yang benar: split per kapabilitas bisnis (Order, Payment, Catalog).
- ❌ Memecah entitas yang wajib konsisten transaksional bersama. (lihat Bagian 4 — ini bisa jadi hard blocker.)
- ❌ Resume-driven / premature. Memecah sebelum boundary domain kelihatan. Domain masih cair → monolith modular lebih murah.
- ❌ Split yang menghasilkan “chatty” coupling. Kalau satu use-case bikin service saling panggil bolak-balik (N+1 antar service), batasnya salah letak (lihat F2).
- ❌ “Biar bisa pakai bahasa/DB baru.” Boleh jadi bonus, tapi bukan justifikasi utama kalau tidak ada driver bisnis/skala.
4. Kriteria Database (bagian TERSULIT — jangan dilewati)
Section titled “4. Kriteria Database (bagian TERSULIT — jangan dilewati)”Kode gampang dipecah; data yang bikin proyek gagal. Target idealnya database-per-service, tapi mahal. Uji tiap pemisahan data:
| # | Uji | Pertanyaan | Konsekuensi kalau diabaikan |
|---|---|---|---|
| D1 | Transaction Boundary | Adakah operasi yang butuh ACID melintasi dua kandidat service? | Kalau ya → mereka kemungkinan satu aggregate, ATAU harus pindah ke saga + eventual consistency dengan semua kompleksitasnya. Ini sering jadi hard blocker. |
| D2 | Foreign Key Lintas Batas | Berapa FK yang putus kalau tabel dipisah? | Tiap FK hilang berubah jadi API call atau duplikasi data. Banyak FK putus = batas salah. |
| D3 | Aggregate Boundary (DDD) | Data mana yang selalu berubah bersama dalam satu unit konsistensi? | Data yang berubah bersama tidak boleh dipisah. |
| D4 | Shared / Master Data | Data referensi (mis. data produk, user) dipakai banyak service — strategi sync-nya apa? | Tanpa strategi → data inkonsisten antar service. Opsi: replikasi read-model, event, atau API. |
| D5 | Reporting / Analytics | Setelah dipisah, join lintas service jadi mahal. Sudah ada rencana? | Perlu CQRS read-model / data warehouse / event stream untuk laporan. |
Kasus panas khas ecommerce: alur Order → Inventory (stok) → Payment. Ini jantung transaksional. Memisah stok dari order membuka masalah race condition / oversell dan butuh idempotency di endpoint yang bisa di-retry. Kalau tim mau memisahkan ini, wajib ada desain eksplisit: reservasi stok, idempotency key, dan strategi saga/kompensasi. Jangan dipisah “asal pisah”.
5. Fitness Function (uji konkret di whiteboard)
Section titled “5. Fitness Function (uji konkret di whiteboard)”Uji sederhana yang bisa langsung dijalankan tim untuk setiap proposal batas:
- F1 — Deploy-Independently Test: “Kalau saya ubah A, bisakah rilis tanpa menyentuh B?” Kalau tidak → jangan pecah.
- F2 — Chatty-Coupling Test: Ambil 1 use-case utama (mis. checkout). Gambar semua network call antar service. Kalau muncul panggilan bolak-balik / N+1 → batas salah letak.
- F3 — Data-Duplication Test: Berapa banyak data harus diduplikasi/di-sync agar service bisa berdiri sendiri? Makin banyak → makin salah batasnya.
- F4 — Coupling Count: Hitung total cross-boundary call di desain. Bandingkan antar opsi batas; pilih yang paling sedikit.
- F5 — Failure Test: Matikan service ini di skenario. Apa yang ikut mati? Kalau seluruh sistem tumbang → belum ter-isolasi dengan benar.
6. SCORECARD — Isi per Kandidat Service
Section titled “6. SCORECARD — Isi per Kandidat Service”Cara skor: tiap kriteria diberi 0 / 1 / 2.
0 = tidak relevan/tidak ada bukti · 1 = ada tapi lemah · 2 = kuat & terbukti
| Kode | Kriteria | Skor (0–2) | Bukti / Argumen (wajib diisi) |
|---|---|---|---|
| J1 | Independent Deployability | ||
| J2 | Independent Scalability | ||
| J3 | Fault Isolation | ||
| J4 | Team Ownership | ||
| J5 | Technology Divergence | ||
| J6 | Bounded Context | ||
| J7 | Compliance/Security Isolation | ||
| J8 | Independent Lifecycle Data | ||
| TOTAL (maks 16) |
Hard Blocker (VETO — cek terpisah, jawab Ya/Tidak):
- HB1 — Butuh transaksi ACID lintas service dengan kandidat lain? (D1)
- HB2 — Banyak FK kritikal putus & tak ada strategi sync? (D2/D4)
- HB3 — Selalu berubah bersamaan (co-change) dengan service lain?
Aturan keputusan:
| Kondisi | Keputusan |
|---|---|
| Ada satu saja Hard Blocker = Ya | ❌ JANGAN SPLIT (atau selesaikan blocker dulu — mis. desain saga) |
| Total ≥ 10 dan tidak ada blocker | ✅ SPLIT — layak jadi service |
| Total 6–9 dan tidak ada blocker | ⚠️ TUNDA — cukup jadi modul dulu, split nanti kalau bukti bertambah |
| Total ≤ 5 | ❌ JANGAN SPLIT — tetap di monolith |
Angka threshold ini bisa disesuaikan tim, tapi prinsipnya: hard blocker selalu mengalahkan total skor. Skor tinggi tidak membenarkan memisah data yang butuh ACID bersama.
6B. SCORECARD DATABASE — Isi per Kandidat Batas Data
Section titled “6B. SCORECARD DATABASE — Isi per Kandidat Batas Data”Kenapa terpisah dari Scorecard 6? Scorecard di Bagian 6 menilai apakah sebuah kapabilitas layak jadi service. Scorecard ini menilai apakah data-nya bisa ikut dipisah dengan aman. Keduanya harus lolos. Sangat mungkin sebuah service layak dipecah, tapi datanya belum bisa — dalam kasus itu: pisahkan kode dulu, data tetap shared sementara (langkah transisi), jangan paksa pisah database.
Arah skor (penting): di sini
2 = data bersih/independen (aman dipisah),0 = data terikat erat (bahaya). Jadi total tinggi = aman dipisah — arahnya sama dengan Scorecard 6.
Isi ini untuk kumpulan tabel yang mau dipindah ke database service baru.
| Kode | Kriteria | Pertanyaan uji | Skor (0–2) | Bukti / Catatan (wajib) |
|---|---|---|---|---|
| DB1 | Independensi Transaksi | Ada operasi yang butuh ACID lintas batas ini? | 2 = tidak ada · 1 = ada tapi toleran eventual consistency · 0 = ada transaksi kritikal wajib ACID lintas batas |
|
| DB2 | Independensi Foreign Key | Berapa FK kritikal putus kalau dipisah? | 2 = ~0 · 1 = sedikit, bisa diganti API/replikasi · 0 = banyak FK inti putus |
|
| DB3 | Kohesi Aggregate | Data ini berubah bersama sebagai satu unit konsistensi (di dalam batas, bukan lintas)? | 2 = satu aggregate utuh · 0 = terbelah, sebagian berubah bareng data service lain |
|
| DB4 | Single Writer | Apakah hanya satu service yang menulis data ini? | 2 = single writer jelas · 1 = multi-writer tapi kolom terpisah · 0 = banyak service menulis kolom yang sama |
|
| DB5 | Master Data / Sync | Kalau ini data referensi dipakai service lain, strategi sync-nya jelas? | 2 = bukan shared / strategi jelas · 1 = shared, strategi masih kasar · 0 = shared tanpa strategi |
|
| DB6 | Independensi Reporting | Laporan/analitik tidak butuh join lintas batas (atau sudah ada read-model/DW)? | 2 = mandiri · 1 = ada rencana CQRS/DW · 0 = laporan bergantung join langsung lintas batas |
|
| DB7 | Stabilitas Skema (co-change) | Skema tabel ini jarang berubah bareng tabel service lain? | 2 = mandiri · 0 = sering migrasi skema serempak |
|
| TOTAL (maks 14) |
Hard Blocker Database (VETO — jawab Ya/Tidak):
- DHB1 — Ada transaksi yang wajib ACID lintas batas & tidak bisa toleran eventual consistency? (DB1 = 0)
- DHB2 — Ada kolom/data yang ditulis banyak service secara konkuren dengan kebutuhan konsistensi kuat? (DB4 = 0)
Aturan keputusan (Database):
| Kondisi | Keputusan |
|---|---|
| Ada satu saja Hard Blocker = Ya | ❌ JANGAN PISAH DATA. Kalau service-nya layak → pisahkan kode saja, data tetap shared / transisi, ATAU desain saga + reservasi + idempotency dulu. |
| Total ≥ 9 dan tidak ada blocker | ✅ PISAH DATA — layak database-per-service. |
| Total 5–8 dan tidak ada blocker | ⚠️ TUNDA — pisahkan kode, data shared sementara (schema/view terpisah dalam DB yang sama sebagai langkah transisi). |
| Total ≤ 4 | ❌ JANGAN PISAH — data tetap menyatu. |
Matriks Kombinasi: Service × Data
Section titled “Matriks Kombinasi: Service × Data”Inilah gunanya dua scorecard. Silangkan hasilnya:
| Data layak dipisah | Data belum layak | |
|---|---|---|
| Service layak dipisah | ✅ Full microservice (punya DB sendiri) | ⚠️ Pisah kode dulu; data shared/transisi, migrasi data belakangan (siapkan saga) |
| Service belum layak | (jarang) rapikan jadi modul dulu | ❌ Tetap di monolith |
Contoh Scorecard Database Terisi — Inventory/Stock vs Order
Section titled “Contoh Scorecard Database Terisi — Inventory/Stock vs Order”Sengaja saya pakai kasus tersulit, supaya tim lihat scorecard ini memveto split yang berisiko:
| Kode | Kriteria | Skor | Bukti |
|---|---|---|---|
| DB1 | Independensi Transaksi | 0 | Pengurangan stok & pembuatan order harus atomik untuk cegah oversell → butuh ACID lintas batas. |
| DB2 | Independensi FK | 1 | order_item → product/stock; bisa diganti reservasi, tapi relasi inti ada. |
| DB3 | Kohesi Aggregate | 1 | Reservasi stok adalah bagian dari lifecycle order. |
| DB4 | Single Writer | 0 | Order flow & job inventory sama-sama menulis jumlah stok. |
| DB5 | Master Data / Sync | 1 | Stok jadi shared, butuh event sync yang belum ada. |
| DB6 | Independensi Reporting | 1 | Laporan penjualan vs stok sering join langsung. |
| DB7 | Stabilitas Skema | 1 | Skema stok berubah cukup sering bareng fitur order. |
| TOTAL | 5 |
Hard Blocker: DHB1 = Ya (DB1 = 0) · DHB2 = Ya (DB4 = 0) Keputusan: ❌ JANGAN PISAH DATA apa adanya. Kalau tetap ingin Inventory jadi service, syaratnya wajib: reservasi stok + idempotency key + saga/kompensasi, dan menerima eventual consistency secara sadar. Sampai desain itu matang, stok & order tetap satu database. — Ini contoh bagus bahwa total skor 5 pun tidak relevan begitu ada hard blocker.
7. Referensi: Kandidat Boundary Khas Ecommerce
Section titled “7. Referensi: Kandidat Boundary Khas Ecommerce”Ini bukan keputusan final — hanya peta awal untuk memandu kajian. Tim tetap wajib mengisi scorecard.
| Kandidat Service | Kekuatan sebagai service | Catatan / Risiko |
|---|---|---|
| Product / Catalog | Kuat (J1, J2, J6). Read-heavy, sering update konten. | Master data dipakai banyak service → butuh strategi sync (D4). |
| Search | Kuat (J2, J5). Butuh Elasticsearch/OpenSearch, scaling & tech beda. | Read-model turunan katalog; boleh eventual consistency. |
| User / Identity / Auth | Kuat (J4, J7). Isolasi keamanan. | Banyak service butuh identitas → sediakan via token/claims, bukan join. |
| Cart | Sedang–kuat (J8). Data ephemeral/TTL, pola tulis tinggi. | Coupling ke Product (harga) & Promo — jaga jangan chatty. |
| Order | Sedang. Ini jantung transaksional. | ⚠️ Kandidat hard blocker: relasi erat ke Inventory & Payment (D1). Hati-hati. |
| Payment | Kuat (J3, J7). Isolasi compliance, integrasi eksternal (gateway). | Konsistensi dengan Order via saga + idempotency, bukan transaksi bersama. |
| Inventory / Stock | Sedang. | ⚠️ Race condition/oversell. Konsistensi ketat dengan Order — desain reservasi + idempotency wajib. |
| Shipping / Logistics | Sedang–kuat (J3, J5). Integrasi kurir eksternal. | Async-friendly; toleran eventual consistency. |
| Promotion / Voucher / Pricing | Sedang. | Coupling ke Cart & Order; rawan chatty (F2). |
| Notification (email/SMS/push) | Kuat & mudah (J3, J8). Fire-and-forget, async. | Kandidat pertama yang paling aman dipecah. Bagus untuk “latihan” tim. |
| Review / Rating | Kuat (J1, J3). Coupling rendah. | Aman dipecah; data relatif independen. |
Rekomendasi urutan migrasi (strangler fig pattern): mulai dari yang coupling rendah & risiko kecil (Notification, Review, Search) untuk membangun fondasi (API gateway, tracing, CI/CD, observability) sebelum menyentuh inti transaksional (Order/Payment/Inventory) yang paling berisiko.
Contoh Scorecard Terisi — Notification Service
Section titled “Contoh Scorecard Terisi — Notification Service”| Kode | Kriteria | Skor | Bukti |
|---|---|---|---|
| J1 | Independent Deployability | 2 | Template email berubah tanpa menyentuh checkout. |
| J2 | Independent Scalability | 1 | Spike saat blast campaign, bisa di-scale sendiri. |
| J3 | Fault Isolation | 2 | Notif gagal → checkout tetap sukses (async, queue). |
| J4 | Team Ownership | 1 | Belum ada tim khusus, tapi domain jelas. |
| J5 | Technology Divergence | 1 | Bisa pakai worker/queue terpisah. |
| J6 | Bounded Context | 2 | Domain “pengiriman pesan” jelas & terisolasi. |
| J7 | Compliance/Security | 0 | Tidak signifikan. |
| J8 | Independent Lifecycle Data | 2 | Log notif punya retensi sendiri, tak terikat order. |
| TOTAL | 11 |
Hard Blocker: HB1 Tidak · HB2 Tidak · HB3 Tidak Keputusan: ✅ SPLIT (total ≥ 10, tanpa blocker). Kandidat aman & bagus untuk memulai migrasi.
8. Definition of Done untuk Kajian Tim
Section titled “8. Definition of Done untuk Kajian Tim”Kajian dianggap selesai bila untuk setiap kandidat service, tim menghasilkan:
- Scorecard Service (Bagian 6) DAN Scorecard Database (Bagian 6B) terisi + bukti tiap kriteria (bukan asumsi).
- Hasil cek Hard Blocker service (HB1–HB3) dan database (DHB1–DHB2), plus posisi di Matriks Service × Data.
- Untuk kandidat yang butuh transaksi lintas service: desain saga/kompensasi + idempotency eksplisit.
- Diagram 1 use-case utama (checkout) menunjukkan cross-boundary call (uji F2).
- Strategi data: mana yang di-own, mana yang di-replikasi/sync (D4), rencana reporting (D5).
- Keputusan akhir: Split / Tunda / Jangan — dengan alasan tertulis.
9. Mitigasi Teknis (kalau service jadi dipecah)
Section titled “9. Mitigasi Teknis (kalau service jadi dipecah)”- Outbox pattern + Saga untuk transaksi terdistribusi (Order↔︎Payment↔︎Inventory).
- Idempotency key di semua endpoint yang bisa di-retry — wajib begitu network jadi unreliable.
- Timeout, retry + exponential backoff, circuit breaker antar service.
- Distributed tracing (correlation ID) sejak hari pertama — tanpa ini debugging jadi mimpi buruk.
- API contract + versioning, plus anti-corruption layer di batas service.
- Strategi konsistensi eksplisit per alur: mana strong, mana eventual.
- Strangler Fig: kupas fitur satu per satu dari monolith, jangan big-bang rewrite.
10. Governance & Architecture Review
Section titled “10. Governance & Architecture Review”10.1 Golden Rule
Section titled “10.1 Golden Rule”Sebuah kandidat Service dinyatakan layak menjadi microservice hanya apabila seluruh kondisi berikut terpenuhi:
- Memiliki justifikasi bisnis yang kuat.
- Mewakili satu Bounded Context yang jelas.
- Memiliki Single Data Owner tanpa kebutuhan transaksi ACID lintas service.
- Dapat di-deploy, di-scale, dimonitor, dan dipulihkan secara independen.
- Kompleksitas tambahan lebih kecil daripada manfaat bisnis yang diperoleh.
Jika salah satu prinsip di atas belum terpenuhi, kandidat sebaiknya tetap menjadi Modular Monolith.
10.2 Architecture Decision Record (ADR)
Section titled “10.2 Architecture Decision Record (ADR)”Setiap keputusan wajib terdokumentasi.
| Field | Isi |
|---|---|
| Service | |
| Keputusan | Split / Tunda / Jangan Split |
| Alasan | |
| Bukti | |
| Referensi | DDD / Fowler / Richardson / Newman / dll |
| Reviewer | |
| Tanggal |
10.3 Evidence Requirement
Section titled “10.3 Evidence Requirement”Semua skor harus memiliki bukti, misalnya:
- Grafik traffic/APM
- Hasil profiling
- Incident/SLA
- Data deployment
- Diagram domain
- Event storming
- Analisis co-change (Git)
Pendapat tanpa bukti tidak boleh menjadi dasar pemecahan.
10.4 Operational Readiness Checklist
Section titled “10.4 Operational Readiness Checklist”Semua service wajib siap dioperasikan.
- Centralized Logging
- Metrics
- Distributed Tracing
- Health Check
- Alerting
- Backup & Restore
- Runbook
- SLO/SLA
- CI/CD
- Rollback
10.5 API Contract Checklist
Section titled “10.5 API Contract Checklist”- Backward Compatible
- API Versioning
- Idempotency
- Timeout
- Retry
- Circuit Breaker
- Correlation ID
- Authentication & Authorization
10.6 Event Contract Checklist
Section titled “10.6 Event Contract Checklist”- Event immutable
- Versioned
- Replayable
- Consumer idempotent
- Tidak menggunakan Event sebagai Command
- Memiliki schema/contract yang terdokumentasi
10.7 Data Ownership Checklist
Section titled “10.7 Data Ownership Checklist”- Single Writer
- Single Owner
- Tidak ada Shared Table
- Tidak ada Shared Schema
- Tidak ada Cross Database Update
- Data diakses melalui API/Event
10.8 Referensi Utama
Section titled “10.8 Referensi Utama”- Eric Evans — Domain-Driven Design (2003)
- Vaughn Vernon — Implementing Domain-Driven Design
- Martin Fowler — Monolith First, Strangler Fig
- Sam Newman — Building Microservices
- Chris Richardson — Microservices Patterns
- Hector Garcia-Molina & Kenneth Salem — Sagas (1987)
- Melvin Conway — Conway’s Law (1968)
- Matthew Skelton & Manuel Pais — Team Topologies
- Neal Ford, Rebecca Parsons, Patrick Kua — Building Evolutionary Architectures
- Michael Nygard — Release It!