Skip to main content
BlogSoftware Development

Microservices vs Monolith: Kapan Harus Dipisah

Haruskah Anda memecah monolith menjadi microservices? Pelajari trade-off nyata, kapan masing-masing arsitektur unggul, dan strategi migrasi yang tidak merusak tim Anda.

Matthews Wong

Software Engineer

Januari 202510 menit baca
Microservices vs Monolith: Kapan Harus Dipisah

Foto oleh Unsplash

Debat microservices vs monolith adalah salah satu keputusan arsitektur paling penting yang dibuat sebuah tim. Salah pilih dan Anda akan tenggelam dalam kompleksitas distributed system sebelum menemukan product-market fit, atau berjuang menskalakan monolith yang sudah menjadi bola kusut. Postingan ini memotong hype untuk memberi Anda kerangka dalam membuat pilihan yang tepat — dan strategi migrasi jika Anda perlu mengubah arah.

DimensiMonolithMicroservices
DeploymentSatu unit deployable, satu pipeline buildDeploy independen per service, kecepatan rilis lebih tinggi tapi butuh lebih banyak koordinasi
DatabaseSatu database bersama, transaksi sederhanaDatabase per service, transaksi lintas-service butuh saga atau eventual consistency
ScalingScale seluruh aplikasi walau cuma satu modul yang sedang tinggi bebanScale hanya service yang jadi bottleneck secara independen
Struktur timCocok untuk tim kecil yang berbagi satu codebaseSesuai Conway's Law, tim terpisah memiliki service masing-masing
Kompleksitas operasionalSatu log stream, satu proses untuk dipantauButuh distributed tracing, service mesh, dan logging terpusat
Isolasi kegagalanSatu bug bisa membuat seluruh aplikasi crashService yang gagal bisa degradasi dengan baik jika sisanya tetap resilient
Paling cocok untukProduk tahap awal, tim kecil, batas domain belum jelasDomain matang dengan bounded context jelas dan kebutuhan scaling independen

Memahami Kedua Arsitektur

Sebuah monolith adalah unit deployable tunggal di mana semua modul — pengguna, pesanan, inventori, penagihan — berbagi proses yang sama dan sering berbagi database yang sama. Arsitektur microservices mengurai modul-modul tersebut menjadi layanan yang dapat di-deploy secara independen yang berkomunikasi melalui jaringan. Perbedaannya terdengar sederhana, tetapi memiliki implikasi mendalam untuk tim, tooling, dan beban operasional Anda.

Monolith: Lebih Sederhana dari yang Terdengar

Monolith mendapat reputasi buruk, tetapi monolith yang terstruktur dengan baik dengan batas modul yang jelas adalah titik awal yang sangat baik untuk hampir semua produk. Anda memiliki satu codebase untuk dinavigasi, transaksi yang mencakup beberapa modul ditangani secara sepele oleh database, debugging mudah (satu proses, satu log stream), dan deployment adalah satu artifact. Beban operasional minimal dibandingkan microservices.

Microservices: Kekuatan dengan Harga

Microservices memungkinkan deployment dan scaling independen per layanan, isolasi kegagalan, dan heterogenitas teknologi — layanan yang berbeda dapat menggunakan bahasa atau database yang berbeda. Tetapi setiap batas layanan yang Anda tambahkan menambah latensi jaringan, kebutuhan distributed tracing, tantangan eventual consistency, dan kompleksitas koordinasi deployment di berbagai repository dan tim.

// Monolith: single shared database, direct function calls
// src/orders/orderService.ts
import { UserRepository } from "../users/userRepository";
import { InventoryRepository } from "../inventory/inventoryRepository";

export class OrderService {
  async placeOrder(userId: string, items: OrderItem[]): Promise<Order> {
    const user = await UserRepository.findById(userId);
    await InventoryRepository.reserveItems(items);
    return OrderRepository.create({ userId, items, status: "pending" });
  }
}

// Microservices: HTTP/message calls across service boundaries
// order-service/src/orderService.ts
export class OrderService {
  async placeOrder(userId: string, items: OrderItem[]): Promise<Order> {
    // Call user-service via HTTP
    const user = await fetch(`http://user-service/users/${userId}`).then(r => r.json());
    // Call inventory-service via message queue
    await messageBroker.publish("inventory.reserve", { items, orderId: newId() });
    return OrderRepository.create({ userId, items, status: "pending" });
  }
}

Buku 'Monolith to Microservices' dari Sam Newman merekomendasikan memulai dengan modular monolith — batas modul internal yang kuat yang diterapkan oleh kode, bukan network call. Ini memberi Anda pemisahan kepentingan tanpa overhead jaringan, dan membuat migrasi di masa depan jauh lebih mudah.

Kapan Masing-Masing Arsitektur Unggul

Pilihan yang tepat bergantung pada ukuran tim, frekuensi deployment, kebutuhan scaling, dan struktur organisasi Anda. Hukum Conway itu nyata: arsitektur sistem Anda akan mencerminkan struktur komunikasi tim Anda. Tim kecil yang membangun satu produk hampir selalu mendapat manfaat dari monolith. Organisasi besar dengan beberapa tim, SLA yang berbeda per layanan, dan kemampuan untuk memiliki pipeline deployment independen adalah rumah alami dari microservices.

Pilih Monolith Ketika

Anda memiliki tim kecil (kurang dari 10 engineer), Anda masih mencari product-market fit dan perlu iterasi cepat, modul Anda berbagi data dan cross-cutting concern yang signifikan, Anda tidak memiliki tim DevOps atau platform khusus untuk mengelola infrastruktur layanan, atau Anda membangun alat internal atau MVP di mana kesederhanaan adalah yang utama.

Pilih Microservices Ketika

Tim Anda berukuran dan terstruktur secara independen berdasarkan layanan, Anda perlu menskalakan komponen tertentu secara independen, layanan yang berbeda memiliki kebutuhan keandalan atau kepatuhan yang berbeda, Anda perlu mendukung beberapa lingkungan deployment secara independen, atau bagian sistem yang berbeda dimiliki oleh tim yang tidak boleh berbagi siklus deployment.

Strategi Migrasi: Strangler Fig Pattern

Jika Anda beralih dari monolith ke microservices, strangler fig pattern adalah pendekatan paling aman. Daripada penulisan ulang besar-besaran (yang hampir selalu gagal), Anda secara bertahap mengekstrak layanan dari monolith sambil tetap menjalankannya. API gateway merutekan request ke monolith atau microservice baru berdasarkan path atau feature flag. Seiring waktu, monolith menyusut saat layanan diekstrak.

Langkah-Langkah Migrasi

Mulai dengan mengidentifikasi bounded context yang paling worth diekstrak — idealnya yang memiliki batas API yang jelas, kebutuhan scaling independen, dan tidak ada data coupling yang erat dengan monolith lainnya. Ekstrak data terlebih dahulu: beri layanan baru database-nya sendiri. Kemudian rutekan traffic melalui API gateway. Validasi layanan baru di bawah load produksi sebelum menghapus kode monolith.

Distributed Monolith: Yang Terburuk dari Keduanya

Anti-pattern paling berbahaya adalah distributed monolith: Anda telah memecah aplikasi menjadi beberapa layanan, tetapi mereka sangat terikat — mereka berbagi database, saling memanggil secara sinkron dalam rantai panjang, dan harus di-deploy bersama. Anda mengambil semua kompleksitas operasional dari microservices tanpa manfaatnya. Sebelum mengekstrak sebuah layanan, pastikan ia benar-benar dapat memiliki data dan melakukan deploy secara independen.

Strategi Migrasi Data

Bagian tersulit dari migrasi microservices adalah data. Gunakan pola database-per-service: setiap layanan memiliki datanya sendiri dan hanya mengeksposnya melalui API-nya. Gunakan event sourcing atau change data capture (CDC) untuk menyinkronkan data antara monolith lama dan layanan baru selama periode transisi. Jangan pernah membiarkan dua layanan berbagi tabel database — itu menciptakan kembali coupling ketat yang ingin Anda hindari.

# Strangler Fig pattern: route by feature flag
# api-gateway/nginx.conf
location /api/users {
  # New microservice handles /users
  proxy_pass http://user-service:3001;
}

location /api/orders {
  # Still monolith for now
  proxy_pass http://monolith:3000;
}

location /api/inventory {
  # Migrated to microservice
  proxy_pass http://inventory-service:3002;
}

Pertimbangan Operasional

Microservices mengalihkan kompleksitas dari kode Anda ke infrastruktur Anda. Anda membutuhkan service discovery, distributed tracing, centralized logging, health check, circuit breaker, dan API gateway sebelum arsitektur microservices Anda siap produksi. Anggarkanlah waktu untuk pekerjaan infrastruktur ini — ini tidak opsional.

Observability: Lifeline Microservices

Dalam monolith, Anda memiliki satu log stream. Dalam microservices, satu request pengguna dapat menyentuh sepuluh layanan. Distributed tracing (OpenTelemetry + Jaeger atau Tempo) memberi Anda visibilitas end-to-end. Structured logging dengan correlation ID memungkinkan Anda memfilter log di seluruh layanan untuk satu request. Metrik dan alerting per layanan (Prometheus + Grafana) memberi tahu Anda layanan mana yang menjadi bottleneck.

Service Mesh dan API Gateway

Service mesh seperti Istio atau Linkerd menangani mTLS antar layanan, load balancing, retry, timeout, dan circuit breaking di level infrastruktur — tanpa mengubah kode aplikasi. API gateway (Kong, AWS API Gateway) menangani autentikasi, rate limiting, dan routing di edge. Keduanya adalah force multiplier untuk arsitektur microservices tetapi menambah kompleksitas operasional tersendiri.

Gunakan health check dan readiness probe pada setiap layanan sejak hari pertama. Layanan yang gagal readiness probe-nya secara otomatis dihapus dari load balancer, mencegah cascading failure sebelum mencapai pengguna.

Membuat Keputusan

Keputusan monolith vs microservices tidak permanen, dan Anda tidak boleh memperlakukannya demikian. Mulai sederhana. Bangun monolith yang terstruktur dengan baik. Ketika bottleneck tertentu atau masalah kepemilikan tim benar-benar membutuhkan ekstraksi layanan, lakukan secara bedah, mengikuti strangler fig pattern. Hindari microservices-by-default dan dekomposisi prematur — keduanya adalah sumber kompleksitas yang tidak perlu yang paling umum dalam tim software modern.

Konsep arsitektur kunci yang dibahas di sini meliputi monolith, microservices, strangler fig, service mesh, and bounded context.

Artikel Terkait

FAQ

Pertanyaan Umum

Jawaban singkat untuk pertanyaan yang paling sering diajukan pembaca tentang topik ini.

Kapan sebuah tim sebaiknya memilih monolith daripada microservices?

Monolith adalah pilihan yang tepat untuk tim kecil di bawah 10 engineer, produk yang masih mencari product-market fit, atau sistem di mana modul-modulnya berbagi data dan cross-cutting concern yang signifikan. Tanpa tim DevOps atau platform khusus untuk mengelola infrastruktur layanan, monolith menghindari beban operasional yang ditimbulkan microservices sebelum Anda benar-benar membutuhkannya.

Apa itu strangler fig pattern dan mengapa lebih aman daripada penulisan ulang besar-besaran?

Strangler fig pattern secara bertahap mengekstrak layanan dari monolith yang sedang berjalan, merutekan traffic melalui API gateway ke monolith atau microservice baru berdasarkan path atau feature flag. Monolith menyusut seiring setiap layanan divalidasi di bawah load produksi sebelum kode monolith yang bersangkutan dihapus. Penulisan ulang besar-besaran hampir selalu gagal karena mengharuskan penggantian segalanya secara bersamaan sambil menjaga sistem tetap berjalan.

Apa itu distributed monolith dan mengapa ia menjadi yang terburuk dari keduanya?

Distributed monolith adalah ketika aplikasi dipecah menjadi beberapa layanan tetapi tetap sangat terikat — mereka berbagi database, saling memanggil secara sinkron dalam rantai panjang, dan harus di-deploy bersama. Ini mengambil semua kompleksitas operasional microservices tanpa manfaatnya seperti scaling atau deployment independen. Sebelum mengekstrak sebuah layanan, ia harus benar-benar dapat memiliki data dan melakukan deploy secara independen.

Bagaimana data sebaiknya ditangani selama migrasi dari monolith ke microservices?

Setiap layanan harus memiliki datanya secara eksklusif dan hanya mengeksposnya melalui API-nya sendiri — ini adalah pola database-per-service. Selama periode transisi, event sourcing atau change data capture (CDC) dapat menyinkronkan data antara monolith lama dan layanan baru. Dua layanan yang berbagi tabel database harus dihindari karena itu menciptakan kembali coupling ketat yang ingin dihindari oleh microservices.

Tooling operasional apa yang diperlukan sebelum microservices siap produksi?

Microservices membutuhkan service discovery, distributed tracing, centralized logging, health check, circuit breaker, dan API gateway sebelum siap untuk produksi. Alat distributed tracing seperti OpenTelemetry dengan Jaeger atau Tempo memberikan visibilitas end-to-end di seluruh layanan, sementara Prometheus dan Grafana mencakup metrik dan alerting per layanan. Service mesh seperti Istio atau Linkerd dapat menangani mTLS, retry, timeout, dan circuit breaking di level infrastruktur tanpa mengubah kode aplikasi.