Ketika bisnis bilang:

“Databasenya lambat.”

atau:

“Kami khawatir database tidak kuat menghadapi campaign bulan depan.”

pembicaraan berubah. Tidak lagi sekadar soal kecepatan query. Sekarang persoalannya apakah satu database masih mampu menopang seluruh bisnis.

Di sinilah Level 3 dari seri fondasi dimulai.

Di bagian sebelumnya, kita sudah membahas latency, throughput, caching, indexing, load balancing, CDN, dan DNS. Teknik-teknik itu membantu kita memeras performa dari satu sistem. Tapi di titik tertentu, memeras tidak cukup. Kita perlu menyebarkan data ke lebih banyak mesin.

Di bagian ini, kita akan membahas:

  • Data Replication
  • Read Replicas
  • Data Partitioning
  • Sharding
  • Consistent Hashing
  • Denormalization
  • Consistency Models
  • CAP Theorem

Tujuannya bukan menjadikan Anda ahli internal database. Tujuannya agar Anda paham trade-off apa yang Anda ambil ketika sistem sudah tidak muat di satu database, dan bisa mengomunikasikan trade-off itu dengan jelas ke tim.


1. Mengapa Satu Database Tidak Lagi Cukup

Sebelum membahas teknik, mari mulai dari pertanyaan: kenapa satu database tidak lagi cukup?

Ada beberapa penyebab umum:

  • Volume data terlalu besar untuk storage satu server.
  • Traffic read terlalu tinggi untuk ditangani satu server.
  • Traffic write terlalu tinggi untuk CPU atau disk satu server.
  • Satu server menjadi single point of failure.
  • Dataset terlalu besar untuk dibackup dalam jendela waktu yang acceptable.
  • Jarak geografis antara user dan database menambah latency yang terlalu besar.

Ketika salah satu dari ini menjadi nyata, pembicaraan bergeser dari “buat query lebih cepat” ke “sebarkan data”.

Dari sudut pandang System Analyst, pertanyaan pertama yang biasanya muncul:

  • Bottleneck-nya CPU, memory, disk I/O, atau network?
  • Workload-nya read-heavy, write-heavy, atau seimbang?
  • Apakah kita bisa toleransi data stale selama beberapa detik?
  • Apakah kita bisa toleransi downtime saat failover?
  • Mana yang lebih mahal: kehilangan data atau kompleksitas?

Tanpa jawaban atas pertanyaan-pertanyaan ini, scaling database jadi tebak-tebakan.


2. Data Replication

Alur replication database: write di primary merambat ke replica dengan delay async

Replication adalah tindakan menyalin data dari satu database ke satu atau beberapa database lain.

Setup umumnya:

                ┌── Replica 1
                │
Primary DB  ────┼── Replica 2
                │
                └── Replica 3

Database primary menerima write. Replica-replica menerima salinan write tersebut. Client kemudian bisa membaca dari primary maupun replica.

Mengapa Replikasi

Replication membantu beberapa masalah sekaligus:

  • Traffic read bisa disebar ke beberapa server.
  • Jika primary gagal, salah satu replica bisa dipromosikan untuk mengambil alih.
  • Replica bisa ditempatkan lebih dekat ke user di region berbeda.
  • Backup dan analytics bisa dijalankan terhadap replica, bukan primary.

Bagaimana Perubahan Menyebar

Tapi replication juga menimbulkan pertanyaan:

Ketika primary mengubah satu baris, kapan replica melihat perubahan itu?

Ada dua pola umum:

Synchronous replication. Primary menunggu sampai minimal satu replica mengonfirmasi bahwa perubahan sudah ditulis. Baru setelah itu primary meng-acknowledge write ke client.

Kelebihan:

  • Replica selalu up to date.
  • Tidak ada risiko kehilangan write terbaru jika primary mati.

Kekurangan:

  • Latency write termasuk round trip ke replica.
  • Jika replica lambat, primary ikut lambat.
  • Jika replica tidak tersedia, write bisa gagal.

Asynchronous replication. Primary menulis secara lokal dan langsung meng-acknowledge client. Replica mengejar belakangan.

Kelebihan:

  • Write di primary sangat cepat.
  • Outage replica tidak memblokir write.

Kekurangan:

  • Replica bisa lag sampai hitungan detik atau menit.
  • Jika primary mati sebelum replica mengejar, write terbaru bisa hilang.

Replication Lag

Jarak antara “data ditulis di primary” dan “data terlihat di replica” disebut replication lag.

Di sinilah banyak bug halus muncul:

  • User mengupdate profil, refresh halaman, lalu melihat nama lama.
  • Sistem e-commerce menampilkan barang masih tersedia, tapi order gagal karena primary sudah menjual unit terakhir.
  • Laporan yang dihasilkan dari replica menunjukkan lebih sedikit baris daripada laporan dari primary.

Lag bukan bug. Lag adalah sifat dari asynchronous replication. Pertanyaannya adalah apakah aplikasi dirancang untuk menangani lag.

Dari sudut pandang System Analyst:

“Berapa lag yang masih acceptable untuk fitur ini, dan apa yang terjadi kalau lag-nya terlampaui?”


3. Read Replicas

Routing read replica: write path ke primary, read path tersebar ke beberapa replica

Read replica adalah replica yang dipakai terutama untuk traffic read. Idenya sederhana: pisahkan workload database sehingga write menuju primary, dan read menuju replica.

                ┌── Read Replica 1
                │
Client ──> App ─┼── Read Replica 2
                │
                └── Primary Database
                     │
                     └── Write

Mengapa Ini Membantu

Banyak aplikasi bersifat read-heavy. Dashboard, listing, laporan, dan halaman pencarian biasanya membaca jauh lebih sering daripada menulis. Dengan menyebarkan read ke replica, primary bisa fokus pada write.

Trade-off

Trade-off-nya tidak gratis:

  • Query read harus toleran terhadap sedikit lag. Bisa melihat data yang sedikit lebih lama.
  • Cross-replica read (misalnya join antar dua replica) jadi rumit.
  • Aplikasi harus aware koneksi mana yang ke mana.
  • Jika satu replica lag parah, sebagian read menjadi lebih lambat dari yang lain.

Kapan Cocok

Read replica cocok ketika:

  • Workload bersifat read-heavy.
  • Data yang sedikit stale bisa diterima (beberapa detik biasanya tidak masalah).
  • Read bisa diklasifikasikan dengan jelas menjadi “butuh data fresh” versus “eventually consistent cukup”.

Kapan Tidak Cocok

Read replica tidak banyak membantu ketika:

  • Write adalah bottleneck. Replica tidak mengurangi beban write.
  • Data harus selalu fresh. Strong consistency diperlukan.
  • Workload berat pada transaksi multi-row yang melintasi banyak tabel. Itu biasanya tetap harus ke primary.

Kesalahan umum adalah mengira bahwa menambah replica selalu membantu. Jika primary CPU-bound karena write, menambah replica hanya menambah biaya tanpa mengurangi bottleneck.


4. Data Partitioning

Data partitioning berdasarkan tanggal, region, atau segment memecah satu tabel besar

Ketika satu tabel menjadi sangat besar, database itu sendiri bisa memecah tabel menjadi bagian-bagian lebih kecil. Inilah yang disebut partitioning.

Partitioning biasanya dilakukan oleh engine database itu sendiri. Aplikasi tetap melihat satu tabel logis, tapi storage-nya terbagi menjadi potongan fisik yang terpisah.

Partition key yang umum:

  • Rentang tanggal: satu partition per bulan atau per tahun.
  • Region: satu partition per geografi.
  • Segment customer: satu partition per tier.
  • Status: satu partition untuk baris aktif, satu untuk arsip.

Contoh dengan sintaks PostgreSQL:

CREATE TABLE orders (
    id BIGINT,
    customer_id BIGINT,
    order_date DATE,
    total_amount DECIMAL(12, 2),
    PRIMARY KEY (id, order_date)
) PARTITION BY RANGE (order_date);

CREATE TABLE orders_2025 PARTITION OF orders
    FOR VALUES FROM ('2025-01-01') TO ('2026-01-01');

CREATE TABLE orders_2026 PARTITION OF orders
    FOR VALUES FROM ('2026-01-01') TO ('2027-01-01');

Mengapa Partitioning Membantu

Partitioning membantu dalam beberapa hal:

  • Query yang menyaring berdasarkan partition key hanya memindai partition yang relevan.
  • Data lama bisa dihapus dengan cepat dengan menghapus satu partition.
  • Bulk load dan maintenance index bisa dilakukan per partition.
  • Beberapa operasi bisa berjalan paralel lintas partition.

Kapan Partitioning Merugikan

Partitioning bukan sulap. Jebakan umum:

  • Query tanpa partition key di WHERE clause memindai semua partition.
  • Memilih partition key yang salah menyebabkan ukuran tidak merata (satu partition besar, banyak yang kecil).
  • Query lintas partition jadi lebih mahal dari yang diharapkan.
  • Join melintasi banyak partition bisa lambat jika strategi partitioning tidak sesuai dengan pola query.

Pertanyaan kuncinya:

“Apakah query paling umum kita menyertakan partition key di WHERE clause?”

Kalau jawabannya tidak, partitioning tidak akan membantu sebanyak yang diharapkan.

Dari sudut pandang System Analyst, partitioning sering jadi langkah pertama yang baik sebelum mempertimbangkan sharding. Partitioning menjaga database tetap sebagai satu unit logis, tapi mendistribusikan beban fisiknya.


5. Sharding

Database sharding memecah data ke server database terpisah berdasarkan rentang key

Partitioning memecah data di dalam satu database. Sharding melangkah lebih jauh: data dipecah ke beberapa server database independen.

Customer A-M ──> Database Shard 1
Customer N-Z ──> Database Shard 2

Tiap shard adalah database sendiri dengan CPU, memory, dan disk sendiri. Bersama-sama, shard-shard tersebut menyimpan seluruh data.

Mengapa Sharding Membantu

  • Storage dan compute bisa scale horizontal. Tambah shard untuk tumbuh.
  • Kegagalan satu shard hanya mempengaruhi data shard tersebut, bukan seluruh sistem.
  • Write bisa didistribusikan ke banyak server.

Mengapa Sharding Sulit

Sharding adalah salah satu keputusan paling kompleks dalam desain database. Trade-off-nya signifikan:

  • Query lintas shard jadi mahal. Query yang butuh data dari dua shard harus menghubungi keduanya.
  • Join lintas shard sulit. Beberapa database sama sekali tidak mendukung.
  • Transaksi lintas shard kompleks dan lambat. Two-phase commit dan protokol sejenis menambah latency dan mode kegagalan.
  • Rebalancing menyakitkan. Ketika satu shard terlalu besar, memindahkan data ke shard baru tidak sepele.
  • Pemilihan shard key sangat kritis. Key yang buruk menyebabkan hot shard di mana satu shard menangani sebagian besar traffic.

Memilih Shard Key

Shard key yang baik:

  • High cardinality. Banyak nilai distinct.
  • Mendistribusikan data secara merata. Tidak ada satu shard yang terlalu besar.
  • Selaras dengan query paling umum. Sebagian besar query menyertakan shard key, jadi hanya menyentuh satu shard.

Shard key yang umum:

  • customer_id untuk sistem yang berpusat pada user.
  • order_id atau invoice_id untuk sistem transaksional.
  • tenant_id di aplikasi multi-tenant SaaS.

Kesalahan umum adalah shard dengan sesuatu yang tidak sesuai dengan pola query. Misalnya, shard berdasarkan created_at untuk sistem yang selalu query berdasarkan customer_id memaksa setiap query menyentuh semua shard.

Scaling database sering berarti memindahkan masalah dari “resource terbatas” ke “kesederhanaan terbatas”.

Sharding memecahkan kapasitas. Sharding juga menciptakan kompleksitas operasional. System Analyst harus bertanya apakah bisnis benar-benar butuh sharding hari ini, atau apakah read replica dan partitioning masih cukup.


6. Consistent Hashing untuk Penempatan Data

Ring consistent hashing: tambah atau hapus node hanya memindahkan sebagian kecil key

Begitu kita shard, kita perlu memutuskan: dari sebuah key, shard mana yang memegang data tersebut?

Pendekatan sederhana:

shard = hash(key) % number_of_shards

Ini berhasil, tapi punya masalah:

Ketika jumlah shard berubah, hampir setiap key dipetakan ulang ke shard berbeda.

Bayangkan kita punya 4 shard dan kita tambahkan shard ke-5. Hash modulo berubah untuk hampir semua key, yang berarti hampir semua record harus dipindahkan. Selama pemindahan, sistem menanggung beban berat, dan query untuk record yang sedang dipindahkan mengembalikan error atau data stale.

Bagaimana Consistent Hashing Membantu

Consistent hashing menyelesaikan ini dengan memetakan key dan server ke ring yang sama. Setiap key ditetapkan ke server berikutnya searah jarum jam di ring.

              Shard A
           ┌─────────┐
       ╱╲  │         │  ╱╲
     ╱    ╲│         │╱    ╲
   ╱   ╱╲  │  Ring   │  ╱╲   ╲
  │   ╱  ╲ │         │ ╱  ╲   │
  │  │ Key│ │         │ │Key │  │
   ╲   ╲ ╱ │         │ ╲ ╱   ╱
     ╲    ╱│         │╲    ╱
       ╲╱  │         │  ╲╱
           └─────────┘
              Shard B

Ketika server baru ditambahkan, hanya key antara server baru dan server sebelumnya searah jarum jam yang dipetakan ulang. Sisanya tetap di tempat.

Ini berguna karena:

  • Menambah node hanya mempengaruhi sebagian kecil key.
  • Menghapus node hanya mempengaruhi slice node tersebut.
  • Rebalancing jauh lebih mulus.

Virtual Nodes

Dalam praktiknya, setiap server fisik direpresentasikan oleh beberapa “virtual node” di ring. Ini membantu mendistribusikan beban lebih merata, karena satu server yang kuat bisa mengambil beberapa slice sekaligus.

Menambah server seharusnya tidak memaksa seluruh dataset untuk “pindahan rumah”.

Consistent hashing dipakai di banyak sistem terdistribusi: cache, key-value store, message queue, bahkan beberapa load balancer. Di bagian sebelumnya seri ini, kita melihat consistent hashing sebagai algoritma load balancing. Di sini kita memakainya sebagai strategi penempatan data. Ide intinya sama: meminimalkan pemetaan ulang ketika cluster berubah.


7. Denormalization

Trade-off denormalization: banyak JOIN versus satu read model yang lebar

Database yang normalized itu rapi. Setiap fakta disimpan satu kali. Nama customer ada di tabel customer. Detail order ada di tabel order. Untuk membangun tampilan dashboard, kita JOIN semuanya.

Normal:
Customer + Order + Order Detail
        ↓ JOIN
Menampilkan Dashboard

Masalahnya, JOIN menjadi mahal dalam skala besar. Query dashboard yang menggabungkan lima tabel melintasi jutaan baris bisa lambat walau index-nya bagus.

Apa yang Denormalization Lakukan

Denormalization dengan sengaja menyimpan data redundant agar read lebih cepat. Tampilan dashboard menjadi tabel atau dokumen tersendiri, sudah ter-JOIN dan siap dibaca.

Denormalized Read Model
        ↓
Langsung digunakan Dashboard

Contoh:

-- Normalized view (lambat di skala besar)
SELECT c.name, o.order_date, oi.product_name, oi.quantity
FROM customers c
JOIN orders o ON c.id = o.customer_id
JOIN order_items oi ON o.id = oi.order_id
WHERE c.id = 1001;

-- Denormalized read model (cepat)
SELECT customer_name, order_date, product_name, quantity
FROM customer_order_summary
WHERE customer_id = 1001;

Read model yang sudah dinormalisasi diperbarui oleh background job setiap kali data di bawahnya berubah.

Trade-off

Denormalization adalah trade-off nyata:

  • Read jadi sangat cepat.
  • Storage membesar karena data terduplikasi.
  • Write jadi lebih kompleks. Setiap perubahan nama customer mungkin perlu memperbarui banyak tabel.
  • Risiko inkonsistensi. Jika background job gagal, read model bisa stale.

Pola ini umum di sistem read-heavy. Search engine, analytics dashboard, dan katalog produk sering memakai denormalized view.

Kapan Menggunakannya

Gunakan denormalization ketika:

  • Query berat yang sama dijalankan berkali-kali.
  • Sedikit staleness di read model masih bisa diterima.
  • Tim bersedia merawat logika sinkronisasi.

Hindari denormalization ketika:

  • Data berubah terlalu sering. Update jadi terlalu mahal.
  • Strong consistency diperlukan. Denormalized view pada dasarnya eventually consistent.
  • Tim tidak mampu menanggung overhead operasional untuk menjaganya tetap sinkron.

8. Model Konsistensi

Model konsistensi: strong, eventual, dan read-your-writes membandingkan kapan replica melihat update

Di database terdistribusi, “data sudah di-update” tidak selalu berarti:

Setiap user melihat nilai baru pada saat yang sama.

Sistem yang berbeda menjanjikan hal berbeda tentang kapan update menjadi terlihat. Janji-janji ini disebut consistency models.

Strong Consistency

Setelah sebuah write selesai, setiap read berikutnya melihat write tersebut (atau yang lebih baru).

Use case:

  • Sistem perbankan. Transfer harus langsung terlihat.
  • Sistem inventory di mana overselling harus dicegah.

Trade-off:

  • Latency write lebih tinggi.
  • Availability lebih rendah saat masalah network.

Eventual Consistency

Jika tidak ada update baru terhadap sebuah data, akhirnya semua replica akan bertemu di nilai yang sama. Tapi tidak ada jaminan tentang kapan.

Use case:

  • Feed media sosial.
  • Katalog produk.
  • View counter.

Trade-off:

  • Availability dan performa sangat tinggi.
  • User bisa melihat data lama untuk sementara.

Read-Your-Writes Consistency

Setelah user menulis sebuah nilai, read berikutnya oleh user tersebut selalu melihat write tersebut. User lain mungkin masih melihat nilai lama sampai replication mengejar.

Use case:

  • User mengupdate foto profil lalu refresh halaman. User tersebut harus melihat foto barunya, meskipun temannya masih melihat yang lama.

Trade-off:

  • Lebih mudah di-reason untuk user yang melakukan perubahan.
  • Tetap eventually consistent untuk user lain.

Causal Consistency

Operasi yang causally related dilihat oleh semua node dalam urutan yang sama. Operasi yang tidak terkait boleh dilihat dalam urutan berbeda.

Use case:

  • Thread komentar. Balasan harus muncul setelah komentar asli, tapi komentar yang tidak saling terkait boleh muncul dalam urutan apa saja.

Mengapa Ini Penting

Pengalaman yang sering membingungkan:

“Saya baru saja update saldo. Saya refresh halaman. Saldo lama masih tampil.”

Apakah sistemnya rusak? Belum tentu. Bisa jadi itu replication lag atau konsekuensi dari eventual consistency.

Dari sudut pandang System Analyst:

“Jaminan konsistensi apa yang dibutuhkan fitur ini, dan jaminan konsistensi apa yang disediakan database yang dipilih?”

Kalau jawabannya tidak cocok, sistem akan bertingkah aneh di titik tertentu.


9. CAP Theorem

CAP theorem: saat network partition, pilih konsistensi atau availability

CAP theorem adalah salah satu ide yang paling sering dikutip dan paling sering disalahpahami di distributed systems. Isinya:

Di sebuah data store terdistribusi, ketika network partition terjadi, Anda harus memilih antara Consistency dan Availability.

Mari kita uraikan.

Tiga Properti

  • Consistency (C). Setiap read melihat write terakhir yang sudah di-commit, atau error.
  • Availability (A). Setiap request menerima respons (non-error), walau tidak bisa menjamin data terbaru.
  • Partition tolerance (P). Sistem tetap berjalan meskipun ada kegagalan network antar node.

Kesalahpahaman Umum

Banyak pengantar bilang:

“Pilih dua dari tiga.”

Ini menyesatkan. Di sistem terdistribusi, network partition pasti terjadi. P bukan pilihan. P adalah keniscayaan. Jadi pertanyaan sebenarnya:

“Ketika partition terjadi, apakah kita mengutamakan C atau A?”

Consistency Saat Partition (CP)

Sistem menolak write (atau read) di sisi partition yang tidak bisa mencapai data terbaru. Sistem lebih memilih mengembalikan error daripada memberikan jawaban yang mungkin salah.

Contoh:

  • Database relasional tradisional yang dikonfigurasi synchronous replication.
  • Beberapa database terdistribusi yang mengutamakan strong consistency.

Availability Saat Partition (AP)

Sistem tetap menerima read dan write di kedua sisi partition. Tiap sisi bekerja dengan data yang dimilikinya. Ketika partition sembuh, sistem melakukan rekonsiliasi.

Contoh:

  • DNS.
  • Sebagian besar key-value store yang eventually consistent.
  • Banyak database NoSQL.

Apa yang Tidak Dijelaskan CAP

CAP membahas apa yang terjadi saat partition. CAP tidak membahas:

  • Latency operasi normal.
  • Performa saat beban tinggi.
  • Biaya rekonsiliasi setelah partition.
  • Berapa lama partition bisa bertahan sebelum konsistensi dipulihkan.

CAP bukan daftar fitur. CAP adalah cara berpikir tentang trade-off ketika network gagal.

Dari sudut pandang System Analyst, pertanyaannya bukan “apakah kita CP atau AP?” tapi “untuk tiap service di sistem kita, apa trade-off yang tepat?”.

Ledger perbankan biasanya CP. Katalog produk biasanya AP. Session store bisa AP dengan read-your-writes. Jawaban yang tepat tergantung requirement bisnis, bukan dari halaman marketing database.


10. Menggabungkan Semua: Contoh Sederhana

Mari gabungkan semua konsep ini ke dalam satu contoh.

Requirement:

“User membuka halaman order history.”

Langkah demi langkah:

Replication

  1. Order service menulis order baru ke primary database.
  2. Perubahan itu di-replikasi secara asynchronous ke dua read replica.

Routing Read Replica

  1. Request order history diidentifikasi sebagai read.
  2. Aplikasi mengarahkannya ke salah satu read replica.

Partitioning dan Sharding

  1. Tabel orders dipartisi berdasarkan order_date (satu partition per kuartal).
  2. Order di-shard berdasarkan customer_id ke empat shard.
  3. Router menghitung shard dari user ID dan mengirim query ke sana.

Consistent Hashing

  1. Router shard menggunakan consistent hashing agar penambahan shard kelima di masa depan tidak memetakan ulang semua customer.

Read Model Denormalisasi

  1. Background job memantau perubahan di tabel normalized.
  2. Job itu mempertahankan view denormalized customer_order_summary, sudah ter-JOIN dan siap dibaca.
  3. Halaman order history membaca dari read model, bukan dari tabel live.

Model Konsistensi

  1. Read model bersifat eventually consistent. User yang baru saja order mungkin melihat order-nya hilang selama beberapa detik.
  2. Halaman detail order memaksa read dari primary untuk menghindari lag tersebut.

Perilaku CAP

  1. Jika network antar region ter-partisi, read replica di region yang terdampak tetap melayani data yang sedikit lebih lama (perilaku AP).
  2. Endpoint order placement menolak write jika tidak bisa mencapai primary (perilaku CP).

Bayangkan masalah di tiap langkah:

Masalah Gejala
Replication lag terlalu tinggi User melihat status order yang outdated
Read replica overloaded Halaman order history lambat
Shard key salah Satu shard jadi hot spot
Job denormalized gagal Read model kosong atau stale
Model konsistensi salah User melihat order-nya hilang tepat setelah order
Network partition diabaikan User melihat data yang konflik antar region

Poinnya: database scaling jarang diperbaiki dengan satu teknik. Ini kombinasi keputusan replication, sharding, caching, dan konsistensi.


11. Kesalahan Umum

Kesalahan-kesalahan ini sering muncul di proyek nyata.

Sharding Terlalu Dini

Sharding menambah kompleksitas yang sangat besar. Banyak sistem yang shard di 10 GB data padahal tidak perlu. Read replica dan partitioning sudah cukup.

Memilih Shard Key yang Salah

Shard key yang menimbulkan hot spot lebih buruk daripada tanpa sharding. Satu shard menanggung sebagian besar traffic, sementara yang lain menganggur.

Mengabaikan Replication Lag

Memperlakukan replica seolah selalu punya data terbaru. Aplikasi bekerja benar di sebagian besar waktu, lalu rusak saat beban tinggi ketika lag membesar.

Denormalisasi Tanpa Strategi Sync

Menyalin data ke read model tanpa rencana jelas untuk menjaga sinkronisasi. Read model melenceng, dan akhirnya user yang notice.

Mengira CAP Berarti “Pilih Dua”

Memperlakukan CAP sebagai checklist alih-alih trade-off saat network partition. Memilih trade-off yang salah untuk fitur yang salah.

Lupa Rebalancing

Mendesain sharding yang bekerja hari ini tapi tidak bisa di-rebalance ketika satu shard membesar. Tim terjebak dengan sistem yang tidak merata.

Melewatkan Observabilitas

Tanpa metrik replication lag, distribusi per shard, dan pelanggaran konsistensi, masalah jadi tidak terlihat sampai user komplain.

Mengoptimasi Satu Jenis Query

Mendesain shard key untuk query paling umum, lalu menyadari kemudian bahwa reporting dan analytics butuh pola akses yang berbeda.


12. Cara System Analyst Membaca Requirement Database

Ketika requirement menyebut database scaling, System Analyst bisa pakai checklist ini:

Workload

  • Apakah sistem read-heavy, write-heavy, atau seimbang?
  • Berapa volume data saat ini dan yang diproyeksikan?
  • Berapa QPS saat ini dan yang diproyeksikan?

Konsistensi

  • Apakah fitur ini butuh strong consistency?
  • Apakah eventual consistency bisa diterima? Untuk berapa lama?
  • Apakah ada fitur di mana user harus melihat tulisannya sendiri segera?

Availability

  • Berapa biaya downtime untuk service ini?
  • Apakah deployment multi-region dibutuhkan?
  • Berapa recovery time objective (RTO) dan recovery point objective (RPO)?

Distribusi

  • Di mana user secara geografis?
  • Apakah kita butuh replica di beberapa region?
  • Apakah kita bisa toleransi latency lintas region?

Strategi Sharding

  • Apa pola akses yang natural? Per user, per tenant, per tanggal?
  • Berapa cardinality shard key?
  • Bisakah kita rebalance tanpa outage besar?

Read Model

  • Apakah ada query yang terlalu berat walau dengan index?
  • Apakah denormalization bisa diterima?
  • Siapa yang merawat read model?

Observabilitas

  • Bisakah kita mengukur replication lag?
  • Bisakah kita mengukur QPS per shard?
  • Apakah kita punya alert untuk pelanggaran konsistensi?

Pertanyaan-pertanyaan ini mengubah permintaan “scale database” yang kabur menjadi kumpulan keputusan desain yang konkret.


13. Penutup

Database scaling bukan satu teknik tunggal. Ini sekumpulan keputusan yang saling terkait:

  • Replication memutuskan berapa salinan data yang ada.
  • Read replica memutuskan bagaimana traffic read didistribusikan.
  • Partitioning memutuskan bagaimana data dipecah dalam satu database.
  • Sharding memutuskan bagaimana data dipecah antar database.
  • Consistent hashing memutuskan di mana setiap key berada.
  • Denormalization memutuskan berapa banyak storage yang kita trade untuk kecepatan read.
  • Consistency models memutuskan apa yang dilihat user dan kapan.
  • CAP mengingatkan kita bahwa saat network partition, setiap sistem membuat trade-off.

Ketika kita membahas requirement database scaling, kita tidak boleh langsung loncat ke solusi. Kita harus bertanya:

“Bagian mana dari workload yang menjadi bottleneck, seberapa fresh data yang dibutuhkan, dan trade-off apa yang bersedia kita terima?”

Pekerjaan performa, pekerjaan aplikasi, dan pekerjaan database saling terhubung. Semakin dalam kita menyelam, semakin penting melihat sistem secara keseluruhan.


Comments