Skip to content

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.


  1. Baca Bagian 1 dulu (prinsip dasar) — ini yang bikin diskusi tidak melebar ke “pokoknya microservices”.
  2. Untuk tiap kandidat service, jalankan pertanyaan di Bagian 2 (justifikasi) dan cek jebakan di Bagian 3 (anti-pattern).
  3. Kajian database di Bagian 4 — ini bagian tersulit dan paling sering diremehkan. Jangan dilewati.
  4. Uji desain dengan fitness function di Bagian 5.
  5. Isi Scorecard di Bagian 6 per service. Ada aturan skor + hard blocker (veto).
  6. 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.


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.

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.

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.


Kajian dianggap selesai bila untuk setiap kandidat service, tim menghasilkan:

  1. Scorecard Service (Bagian 6) DAN Scorecard Database (Bagian 6B) terisi + bukti tiap kriteria (bukan asumsi).
  2. Hasil cek Hard Blocker service (HB1–HB3) dan database (DHB1–DHB2), plus posisi di Matriks Service × Data.
  3. Untuk kandidat yang butuh transaksi lintas service: desain saga/kompensasi + idempotency eksplisit.
  4. Diagram 1 use-case utama (checkout) menunjukkan cross-boundary call (uji F2).
  5. Strategi data: mana yang di-own, mana yang di-replikasi/sync (D4), rencana reporting (D5).
  6. 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.

Sebuah kandidat Service dinyatakan layak menjadi microservice hanya apabila seluruh kondisi berikut terpenuhi:

  1. Memiliki justifikasi bisnis yang kuat.
  2. Mewakili satu Bounded Context yang jelas.
  3. Memiliki Single Data Owner tanpa kebutuhan transaksi ACID lintas service.
  4. Dapat di-deploy, di-scale, dimonitor, dan dipulihkan secara independen.
  5. Kompleksitas tambahan lebih kecil daripada manfaat bisnis yang diperoleh.

Jika salah satu prinsip di atas belum terpenuhi, kandidat sebaiknya tetap menjadi Modular Monolith.

Setiap keputusan wajib terdokumentasi.

Field Isi
Service
Keputusan Split / Tunda / Jangan Split
Alasan
Bukti
Referensi DDD / Fowler / Richardson / Newman / dll
Reviewer
Tanggal

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.

Semua service wajib siap dioperasikan.

  • Centralized Logging
  • Metrics
  • Distributed Tracing
  • Health Check
  • Alerting
  • Backup & Restore
  • Runbook
  • SLO/SLA
  • CI/CD
  • Rollback
  • Backward Compatible
  • API Versioning
  • Idempotency
  • Timeout
  • Retry
  • Circuit Breaker
  • Correlation ID
  • Authentication & Authorization
  • Event immutable
  • Versioned
  • Replayable
  • Consumer idempotent
  • Tidak menggunakan Event sebagai Command
  • Memiliki schema/contract yang terdokumentasi
  • Single Writer
  • Single Owner
  • Tidak ada Shared Table
  • Tidak ada Shared Schema
  • Tidak ada Cross Database Update
  • Data diakses melalui API/Event
  • 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!

Dokumen ini merupakan sintesis praktik-praktik tersebut dan dimaksudkan sebagai standar internal untuk mengevaluasi usulan pemecahan service.

Section titled “Dokumen ini merupakan sintesis praktik-praktik tersebut dan dimaksudkan sebagai standar internal untuk mengevaluasi usulan pemecahan service.”