Merancang arsitektur data untuk sistem modular dan terdistribusi: level pemodelan conceptual-logical-physical, polyglot persistence, spektrum konsistensi strong vs eventual, kepemilikan data antar modul, serta pola outbox dan CQRS — dipraktikkan pada studi kasus e-commerce

Setelah di episode 7 kita mendesain modul dengan boundary tegas — zona publik eksplisit, larangan akses tabel lintas modul, dan fitness function penjaganya — pada episode ini kita garap sisi yang paling sering menentukan umur panjang sebuah arsitektur: data.
Mengapa data begitu menentukan? Karena skema data adalah komponen paling mahal diubah. Kode bisa di-refactor dalam hitungan hari; data yang salah model harus dimigrasi bertahun-tahun sambil sistem tetap berjalan. Dan begitu data tersebar ke banyak penyimpanan (yang hampir pasti terjadi), pertanyaan konsistensi menjadi pusat seluruh desain.
Pemodelan data bekerja di tiga level abstraksi — dan architect utamanya tinggal di dua level pertama:
Customer melakukan Order yang berisi Product. Bahasa bounded context dari episode 4 hidup di sini.Kesalahan klasik tim: melompat langsung dari requirement ke physical ("buatkan tabelnya") sehingga keputusan struktural terselubung di dalam DDL. Kebiasaan sehat: gambar conceptual bersama stakeholder, validasi logical bersama senior engineer, baru delegasikan physical.
Tidak ada satu database untuk semua kebutuhan — pilih per pola akses:
| Kebutuhan | Pilihan Alami | Alasan |
|---|---|---|
| Transaksi & invariant kuat | PostgreSQL/MySQL | ACID, constraint, join |
| Dokumen fleksibel | MongoDB | Skema evolutive, nested doc |
| Cache & session | Redis | In-memory, TTL, struktur data |
| Full-text search | Elasticsearch/OpenSearch | Inverted index, ranking |
| Analitik besar | ClickHouse/BigQuery | Columnar, agregasi cepat |
| Time series | TimescaleDB/InfluxDB | Compaction, retention policy |
Prinsip penggunaannya disiplin: setiap tambahan datastore adalah biaya operasional permanen (backup, monitoring, keamanan, keterampilan tim). Polyglot bukan lisensi menumpuk teknologi; ia jawaban untuk kebutuhan akses yang benar-benar berbeda.
Tip
Heuristik aman: mulai dengan satu relational database yang solid untuk seluruh modul (dengan schema terpisah). Tambahkan datastore baru hanya saat quality scenario episode 5 menuntutnya — misal latency search yang tak bisa dicapai LIKE atau throughput analitik yang mengganggu jalur transaksional.
Konsistensi bukan saklar on/off, melainkan spektrum:
Strong Read-your-writes Eventual
(ACID lokal) (session sticky) (lag replikasi terlihat)
▲ ▲
payment, stok feed, rekomendasi,
checkout notifikasi, analitikDua kerangka teori di baliknya cukup dipahami secara intuisi:
Keputusan praktisnya per-aliran-data, bukan per-sistem: jalur checkout studi kasus kita butuh strong consistency untuk stok dan pembayaran; feed aktivitas dan email marketing nyaman eventual.
Aturan kepemilikan turun langsung dari boundary modul episode 7:
StockChanged; siapa pun yang butuh salinan, update salinannya sendiri.Di sinilah outbox pattern masuk. Masalah klasik: modul menulis database lalu menerbitkan event ke broker — dua langkah yang bisa gagal terpisah (sukses commit, gagal publish, atau sebaliknya). Solusinya:
1. Dalam SATU transaksi DB:
tulis data bisnis + tulis event ke tabel outbox
2. Relay proses baca outbox → publish ke broker → tandai terkirim
3. Consumer idempotent (event bisa terkirim lebih dari sekali)Transaksi lokal menjamin data dan event sama-sama ada atau sama-sama tidak; relay menambah at-most-sekali-jeda, consumer menangani duplikasi. Pola ini akan kita pakai eksplisit di saga episode 12 dan Kafka episode 13.
Command Query Responsibility Segregation memisahkan model tulis (dinormalisasi, menjaga invariant) dari model baca (didenormalisasi, dioptimalkan query). Sinkronisasi keduanya lewat event — final consistency.
Kapan layak:
Kapan berlebihan: CRUD sederhana dengan traffic seimbang — CQRS di sana hanya menambah dua model untuk dirawat tanpa manfaat terukur.
Mari terapkan. Peta kepemilikan data:
postgreSQL: # satu cluster, schema per modul
catalog_schema: products, categories
ordering_schema: orders, order_items, outbox
inventory_schema: stock_items, reservations
payment_schema: charges, refunds
redis: cache & session
elasticsearch: indeks produk (baca katalog)
kafka: topik event antar modul (via outbox)Alur kritis checkout dengan konsistensi yang tepat per bagian:
1. reserveStock() → transaksi ACID di inventory_schema (strong)
2. createOrder() → transaksi ACID di ordering_schema (strong)
3. charge() ke gateway → idempotency key, retry aman (strong hasil)
4. PaymentReceived → outbox → kafka (eventual)
5. shipping menerima → jadwalkan pengiriman (eventual)
6. analytics menerima → pipeline laporan (eventual)Perhatikan desainnya: strong consistency dibayar hanya di tiga langkah pertama yang benar-benar menuntutnya. Sisa aliran memakai eventual via event — inilah komposisi konsistensi yang bijak, bukan strong-everywhere yang lambat atau eventual-everywhere yang berbahaya.
Important
Pertanyaan uji untuk setiap data lintas modul: "berapa detik stale yang masih bisa diterima bisnis?" Kalau jawabannya nol, pakai panggilan sinkron atau transaksi lokal di modul pemilik. Kalau lima detik cukup, event + read model selalu lebih murah.
Inti yang harus dibawa pulang:
Di episode 9 selanjutnya kita bahas API design & contracts — merancang interface antar modul dan keluar sistem, versioning tanpa mematahkan konsumen, dan contract testing agar perubahan tidak lagi mengejutkan. Sampai jumpa!