Mengupas pilar utama arsitektur microservices: batas layanan berbasis bounded context, database per service tanpa join lintas layanan, API gateway sebagai pintu masuk tunggal, serta komunikasi sinkron dan asinkron, lengkap dengan pengenalan studi kasus tokokita

Setelah di episode 1 kita memahami sejarah dan alasan "kenapa" microservices ada — plus klarifikasi bahwa modular monolith adalah titik awal yang baik — pada episode ini kita masuk ke bagaimana arsitektur microservices dirancang. Ini adalah episode konseptual paling penting di seluruh series: empat pilar yang akan menemani kalian dari episode 3 sampai 27.
Mengapa episkode ini penting? Karena sebagian besar kegagalan adopsi microservices bukan disebabkan oleh teknologi, melainkan oleh batas layanan yang salah. Memecah aplikasi jadi 20 layanan kacau jauh lebih buruk daripada satu monolith yang rapi. Empat pilar berikut adalah panduannya.
Pilar pertama berasal dari Domain-Driven Design (DDD). Setiap layanan harus mewakili satu bounded context: sebuah batas eksplisit di mana sebuah konsep domain memiliki makna yang konsisten. Di dalam satu context, tim memakai ubiquitous language — satu kosa kata yang sama antara product owner, engineer, dan kode.
Contoh: kata "order" punya makna berbeda di context yang berbeda. Di order-service, order adalah status transaksi. Di payment-service, "order" hanyalah referensi order_id — ia tidak punya field status order, hanya amount yang harus dibayar. Mencampur keduanya dalam satu tabel (seperti di monolith) membuat makna satu domain bocor ke domain lain.
Beberapa heuristic yang lazim dipakai:
auth-service # identitas: user, credential, token
product-service # katalog: produk, kategori, stok, inventory
cart-service # keranjang: session cart, qty, snapshot harga
order-service # pesanan: order, order_items, state machine
payment-service # pembayaran: transaksi, status payment, amount
notification-service # notifikasi: email, sms, template pesanSetiap layanan memiliki database atau schema sendiri. order-service tidak membaca tabel users milik auth-service secara langsung; ia menyimpan user_id sebagai foreign key konseptual tanpa join. Tidak ada service lain yang boleh mengeksekusi SQL ke database milik layanan lain — semua akses harus lewat API layanan pemilik data.
Konsekuensinya tegas dan harus diterima apa adanya:
auth_service_db → users, refresh_tokens
product_service_db → products, categories, inventories
order_service_db → orders, order_items
payment_service_db → payments, transactions
notification_service_db → notifications, outbox_emailsCaution
Kesalahan umum: membiarkan beberapa layanan memakai satu database yang sama demi "praktis". Ini menghancurkan independensi — satu schema change bisa membawa turun banyak layanan dan mengubah microservices menjadi distributed monolith (satu database, banyak jaringan). Prinsipnya: jika sebuah layanan tidak bisa men-deploy dan berjalan tanpa meminta izin schema ke layanan lain, batasnya salah.
Semua client (web, mobile app) masuk lewat satu pintu: API Gateway. Gateway bertanggung jawab atas:
/api/auth/* ke auth-service, /api/products/* ke product-service.BFF (Backend-for-Frontend) adalah varian di mana tiap jenis client punya gateway khusus sendiri — misalnya bff-web dan bff-mobile — karena kebutuhan payload keduanya berbeda. BFF dipakai bila client mobile dan web mulai memaksa gateway melakukan terlalu banyak hal.
Client (web/app) → api-gateway
├── /api/auth/* → auth-service
├── /api/products/* → product-service
├── /api/cart/* → cart-service
└── /api/orders/* → order-serviceDua gaya komunikasi antar layanan:
Request → response dalam satu waktu, layanan pemanggil memblokir sampai jawaban tiba. Cocok untuk operasi yang memang butuh jawaban langsung: login, cek detail produk, submit order. Dipakai untuk command yang butuh konfirmasi.
Layanan pemanggil mengirim event dan tidak menunggu. Event dikonsumsi oleh siapa pun yang peduli (notification, analytics). Ini memutus coupling langsung antar layanan dan memberi eventual consistency. Dipakai untuk hal-hal seperti "user baru terdaftar" — tidak ada yang perlu menunggu apakah email selamat datang berhasil terkirim.
Perbandingan singkat:
| Aspek | Sinkron | Asinkron |
|---|---|---|
| Coupling | Langsung ke pemilik data | Lepas (decoupled) |
| Konsistensi | Langsung | Eventual |
| Kegagalan | Failure langsung terlihat | Buffer di event bus |
| Cocok untuk | Request-response (command) | Notifikasi, integrasi, fan-out |
Sepanjang series kita membangun tokokita, e-commerce dengan alur utama: browse produk → keranjang → checkout → bayar → notifikasi email. Tujuh proses berjalan:
Layani ini ditenagai PostgreSQL (data), Redis (cache/session), dan Kafka (event bus). Di episode 3 kita akan menuliskan struktur monoreponya.
Episode 2 meletakkan empat pilar arsitektur microservices:
Studi kasus tokokita siap dibangun dengan tujuh proses + gateway.
Di episode 3 selanjutnya, kita akan setup struktur projek tokokita (monorepo) — membandingkan monorepo vs polyrepo, membangun struktur folder lengkap dengan shared packages, dan menjalankan environment dev (PostgreSQL, Redis, Kafka) lewat Docker Compose. Sampai jumpa di episode 3!