Database

Apache CouchDB: NoSQL Document Database Lengkap

Pelajari Apache CouchDB dari dasar — document model, replication, views (MapReduce), Mango queries, dan clustering untuk distributed apps

1. Pengenalan CouchDB

Apache CouchDB adalah database NoSQL berbasis dokumen yang menyimpan data dalam format JSON. Dikembangkan oleh Apache Software Foundation, CouchDB terkenal dengan fitur multi-master replication — memungkinkan sinkronisasi data antar server bahkan dalam kondisi offline.

Karakteristik Utama CouchDB

FiturDeskripsi
Document-OrientedData disimpan sebagai JSON document dengan field yang fleksibel
Multi-Master ReplicationSetiap node bisa menerima write, sync satu sama lain
Offline-FirstBekerja tanpa koneksi internet, sync saat online kembali
RESTful APISemua operasi melalui HTTP — GET, PUT, POST, DELETE
Eventual ConsistencyData akhirnya konsisten di semua node, tidak instant
Built-in Conflict ResolutionMendeteksi dan menangani konflik saat replikasi
Fauxton Web UIAdmin dashboard bawaan di browser

CouchDB vs Database Lain

AspekCouchDBMongoDBPostgreSQL
TipeDocument NoSQLDocument NoSQLRelational SQL
FormatJSONBSON (binary JSON)Rows & Columns
APIRESTful HTTPWire ProtocolSQL via TCP
ReplicationMulti-masterReplica Set (primary-secondary)Primary-replica
QueryMango / MapReduce ViewsMQL (Mongo Query Language)SQL
SchemaSchema-lessSchema-lessSchema-enforced
Best ForOffline-first, mobile, syncGeneral purpose NoSQLComplex queries, ACID
Diagram: Arsitektur CouchDB
+--------------------------------------------------------------------+
|                  ARSITEKTUR COUCHDB                                  |
|                                                                    |
|  +------------------+    +------------------+    +---------------+  |
|  |   Server A       |    |   Server B       |    |  Mobile App   |  |
|  |  +------------+  |    |  +------------+  |    |  +----------+ |  |
|  |  | Database   |  |<-->|  | Database   |  |<-->|  | PouchDB  | |  |
|  |  | (shard 1)  |  |    |  | (shard 2)  |  |    |  | (local)  | |  |
|  |  +------------+  |    |  +------------+  |    |  +----------+ |  |
|  |  | Views      |  |    |  | Views      |  |    |               |  |
|  |  +------------+  |    |  +------------+  |    |  Replication  |  |
|  +------------------+    +------------------+    +---------------+  |
|                                                                    |
|  API: HTTP REST                                                    |
|  GET /database/document_id                                         |
|  PUT /database/document_id  { JSON body }                          |
+--------------------------------------------------------------------+

2. Instalasi & Setup

Instalasi CouchDB

Bash — Instalasi CouchDB
# =============================================
# Docker (recommended untuk development)
# =============================================
docker run -d --name couchdb \
  -e COUCHDB_USER=admin \
  -e COUCHDB_PASSWORD=password123 \
  -p 5984:5984 \
  apache/couchdb:3.3

# =============================================
# Ubuntu/Debian
# =============================================
# Tambah repository
curl -L https://couchdb.apache.org/repo/keys.asc | sudo apt-key add -
echo "deb https://apache.jfrog.io/artifactory/couchdb-deb/ jammy main" | \
  sudo tee /etc/apt/sources.list.d/couchdb.list

sudo apt update
sudo apt install couchdb

# =============================================
# macOS
# =============================================
brew install couchdb
brew services start couchdb

# =============================================
# Verifikasi instalasi
# =============================================
curl http://localhost:5984/
# Output: {"couchdb":"Welcome","version":"3.3.3",...}

# Akses Fauxton (Web UI):
# http://localhost:5984/_utils/

Konfigurasi Awal

Bash — Setup CouchDB
# Setup single-node cluster
curl -X POST http://localhost:5984/_cluster_setup \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{"action":"enable_single_node","username":"admin","password":"password123","bind_address":"0.0.0.0","port":5984}'

# Buat database baru
curl -X PUT http://localhost:5984/toko_online \
  -u admin:password123

# Lihat semua database
curl http://localhost:5984/_all_dbs \
  -u admin:password123

# Hapus database
curl -X DELETE http://localhost:5984/toko_online \
  -u admin:password123

Node.js: nano Library

JavaScript — nano Client
// Instalasi nano (CouchDB client untuk Node.js)
// npm install nano

const Nano = require('nano');
const nano = Nano('http://admin:***@localhost:5984');

async function main() {
  // Buat database
  try {
    await nano.db.create('toko_online');
    console.log('Database berhasil dibuat');
  } catch (err) {
    if (err.statusCode === 412) {
      console.log('Database sudah ada');
    }
  }

  // Gunakan database
  const db = nano.use('toko_online');

  // Insert document
  const response = await db.insert({
    nama: 'Budi Santoso',
    email: 'budi@email.com',
    kota: 'Jakarta',
    is_active: true,
    tanggal_daftar: new Date().toISOString()
  });
  console.log('Document ID:', response.id);
  console.log('Revision:', response.rev);
}

main().catch(console.error);

3. Documents & JSON

Di CouchDB, semua data disimpan sebagai document dalam format JSON. Setiap document punya _id (unik) dan _rev (revision) yang di-manage otomatis oleh CouchDB.

Struktur Document

JSON — CouchDB Document
{
  "_id": "pelanggan_001",
  "_rev": "3-1a2b3c4d5e6f",
  "tipe": "pelanggan",
  "nama": "Budi Santoso",
  "email": "budi@email.com",
  "telepon": "08123456789",
  "alamat": {
    "jalan": "Jl. Sudirman No. 123",
    "kota": "Jakarta",
    "provinsi": "DKI Jakarta",
    "kode_pos": "12190"
  },
  "pesanan": [
    {
      "id_produk": "prod_001",
      "nama_produk": "Laptop ASUS",
      "harga": 12000000,
      "jumlah": 1
    },
    {
      "id_produk": "prod_002",
      "nama_produk": "Mouse Logitech",
      "harga": 250000,
      "jumlah": 2
    }
  ],
  "is_active": true,
  "tags": ["premium", "jakarta"],
  "created_at": "2026-06-26T10:00:00Z"
}

Field Khusus CouchDB

FieldDeskripsiContoh
_idID unik document (bisa di-set manual atau auto-generate)"pelanggan_001"
_revRevision — di-update setiap perubahan"3-1a2b3c4d"
_deletedFlag soft deletetrue
_attachmentsFile binary yang di-attach ke document{ "foto.jpg": {...} }
💡 Design Document

Untuk mengelola struktur document, gunakan field tipe (atau type) sebagai discriminator. CouchDB tidak punya "table" seperti RDBMS — semua document di satu database, di-filter berdasarkan tipe.

4. CRUD Operations

Semua operasi di CouchDB melalui HTTP REST API. Berikut panduan lengkap CRUD:

Create — Membuat Document

Bash — Create Document (cURL)
# POST: Auto-generate _id
curl -X POST http://localhost:5984/toko_online \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{
    "tipe": "pelanggan",
    "nama": "Sari Dewi",
    "email": "sari@email.com",
    "kota": "Bandung",
    "is_active": true
  }'
# Response: {"ok":true,"id":"abc123...","rev":"1-def456..."}

# PUT: Tentukan _id sendiri
curl -X PUT http://localhost:5984/toko_online/pelanggan_001 \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{
    "tipe": "pelanggan",
    "nama": "Budi Santoso",
    "email": "budi@email.com",
    "kota": "Jakarta",
    "is_active": true
  }'

Read — Membaca Document

Bash — Read Document (cURL)
# GET: Ambil document berdasarkan ID
curl http://localhost:5984/toko_online/pelanggan_001 \
  -u admin:password123

# GET: Ambil dengan revisi tertentu
curl "http://localhost:5984/toko_online/pelanggan_001?rev=2-abc123" \
  -u admin:password123

# HEAD: Cek apakah document ada
curl -I http://localhost:5984/toko_online/pelanggan_001 \
  -u admin:password123

# GET: Ambil beberapa document sekaligus
curl -X POST http://localhost:5984/toko_online/_all_docs \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{"include_docs": true, "keys": ["pelanggan_001", "pelanggan_002"]}'

# GET: Semua document (dengan pagination)
curl "http://localhost:5984/toko_online/_all_docs?include_docs=true&limit=10" \
  -u admin:password123

Update — Memperbarui Document

Bash — Update Document (cURL)
# PUT: Update document (WAJIB menyertakan _rev terbaru)
curl -X PUT http://localhost:5984/toko_online/pelanggan_001 \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{
    "_rev": "2-abc123def456",
    "tipe": "pelanggan",
    "nama": "Budi Santoso",
    "email": "budi_baru@email.com",
    "kota": "Surabaya",
    "is_active": true
  }'
# Response: {"ok":true,"id":"pelanggan_001","rev":"3-789ghi..."}

Delete — Menghapus Document

Bash — Delete Document (cURL)
# DELETE: Hapus document (WAJIB _rev)
curl -X DELETE "http://localhost:5984/toko_online/pelanggan_001?rev=3-789ghi" \
  -u admin:password123

# CouchDB melakukan soft delete — document ditandai _deleted:true
# Data tetap ada di database sampai compaction

CRUD dengan Node.js (nano)

JavaScript — CRUD dengan nano
const Nano = require('nano');
const nano = Nano('http://admin:***@localhost:5984');
const db = nano.use('toko_online');

async function crudDemo() {
  // CREATE
  const createResult = await db.insert({
    tipe: 'pelanggan',
    nama: 'Rina Wati',
    email: 'rina@email.com',
    kota: 'Yogyakarta'
  });
  const docId = createResult.id;

  // READ
  const doc = await db.get(docId);
  console.log('Nama:', doc.nama);

  // UPDATE (wajib sertakan _rev)
  doc.email = 'rina_baru@email.com';
  doc.kota = 'Semarang';
  const updateResult = await db.insert(doc);
  console.log('New revision:', updateResult.rev);

  // DELETE
  await db.destroy(docId, updateResult.rev);
  console.log('Document deleted');

  // BATCH INSERT
  const batchDocs = [
    { tipe: 'produk', nama_produk: 'Laptop', harga: 12000000 },
    { tipe: 'produk', nama_produk: 'Mouse', harga: 250000 },
    { tipe: 'produk', nama_produk: 'Keyboard', harga: 500000 }
  ];
  const batchResult = await db.bulk({ docs: batchDocs });
  console.log('Batch inserted:', batchDocs.length, 'documents');
}

crudDemo().catch(console.error);

5. Replication & Sync

Fitur terkuat CouchDB adalah multi-master replication. Setiap node bisa menerima write dan menyinkronkan perubahan ke node lain. Ini mendukung skenario offline-first dan distributed.

Cara Kerja Replication

Diagram: Multi-Master Replication
+--------------------------------------------------------------------+
|              MULTI-MASTER REPLICATION                                |
|                                                                    |
|  Server A (Jakarta)         Server B (Bandung)                     |
|  +-------------------+      +-------------------+                  |
|  | DB: toko_online   |<---->| DB: toko_online   |                  |
|  | Write: OK         |      | Write: OK         |                  |
|  | Read:  OK         |      | Read:  OK         |                  |
|  +-------------------+      +-------------------+                  |
|         ^                           ^                              |
|         |                           |                              |
|  Mobile App (Offline)        Tablet (Offline)                      |
|  +-------------------+      +-------------------+                  |
|  | PouchDB (local)   |      | PouchDB (local)   |                  |
|  | Write: OK         |      | Write: OK         |                  |
|  | Sync saat online  |      | Sync saat online  |                  |
|  +-------------------+      +-------------------+                  |
|                                                                    |
|  Semua node bisa WRITE. Sync terjadi otomatis.                     |
|  Conflict di-handle berdasarkan revision tree.                     |
+--------------------------------------------------------------------+

Menjalankan Replication

Bash — CouchDB Replication
# Replication satu arah: Server A -> Server B
curl -X POST http://localhost:5984/_replicate \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{
    "source": "http://localhost:5984/toko_online",
    "target": "http://server-b:5984/toko_online",
    "continuous": false
  }'

# Replication dua arah (bi-directional)
curl -X POST http://localhost:5984/_replicate \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{
    "source": "http://localhost:5984/toko_online",
    "target": "http://server-b:5984/toko_online",
    "continuous": true,
    "create_target": true
  }'

# Filtered replication: hanya sync data tertentu
curl -X POST http://localhost:5984/_replicate \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{
    "source": "http://localhost:5984/toko_online",
    "target": "http://server-b:5984/toko_online",
    "continuous": true,
    "filter": "app/hanya_pelanggan_aktif"
  }'

Replication Filter

JavaScript — Replication Filter
// Design Document dengan filter function
// Simpan sebagai _design/app di database

{
  "_id": "_design/app",
  "filters": {
    "hanya_pelanggan_aktif": "function(doc, req) {
      return doc.tipe === 'pelanggan' && doc.is_active === true;
    }",
    "hanya_produk": "function(doc, req) {
      return doc.tipe === 'produk';
    }"
  }
}

// Menggunakan filter dengan Node.js nano
const Nano = require('nano');
const nano = Nano('http://admin:***@localhost:5984');
const db = nano.use('toko_online');

// Simpan design document
await db.insert({
  _id: '_design/app',
  filters: {
    hanya_pelanggan_aktif: function(doc, req) {
      return doc.tipe === 'pelanggan' && doc.is_active === true;
    }.toString()
  }
});

// Jalankan filtered replication
const replicator = nano.db.use('_replicator');
await replicator.insert({
  _id: 'sync_ke_mobile',
  source: 'http://localhost:5984/toko_online',
  target: 'http://mobile-server:5984/toko_online',
  continuous: true,
  filter: 'app/hanya_pelanggan_aktif'
});

PouchDB: CouchDB di Browser/Mobile

JavaScript — PouchDB (Offline-First)
// PouchDB: CouchDB di browser/mobile
// npm install pouchdb

const PouchDB = require('pouchdb');
const localDB = new PouchDB('toko_online');
const remoteDB = new PouchDB('http://admin:***@localhost:5984/toko_online');

// Simpan data secara lokal (bisa offline)
await localDB.put({
  _id: 'pelanggan_001',
  nama: 'Budi Santoso',
  email: 'budi@email.com'
});

// Sync dengan server (otomatis reconcile)
localDB.sync(remoteDB, {
  live: true,    // Continuous sync
  retry: true    // Retry jika gagal
}).on('change', function(info) {
  console.log('Sync change:', info.direction);
}).on('error', function(err) {
  console.error('Sync error:', err);
});

6. Views & MapReduce

Views adalah mekanisme query utama di CouchDB. Menggunakan paradigma MapReduce untuk mengindeks dan meng-aggregate data.

MapReduce Concepts

KomponenFungsiAnalogi SQL
Map FunctionUntuk setiap document, emit key-value pairsSELECT ... WHERE ...
Reduce FunctionAggregate hasil map (count, sum, stats)GROUP BY + SUM/COUNT
ViewKombinasi Map + Reduce, diindeks otomatisMaterialized View
JavaScript — CouchDB Views
// Design Document dengan Views
// Simpan sebagai _design/toko di database

{
  "_id": "_design/toko",
  "views": {
    "pelanggan_per_kota": {
      "map": "function(doc) {
        if (doc.tipe === 'pelanggan' && doc.is_active) {
          emit(doc.kota, doc.nama);
        }
      }"
    },
    "jumlah_pelanggan_per_kota": {
      "map": "function(doc) {
        if (doc.tipe === 'pelanggan' && doc.is_active) {
          emit(doc.kota, 1);
        }
      }",
      "reduce": "_count"
    },
    "total_belanja_per_pelanggan": {
      "map": "function(doc) {
        if (doc.tipe === 'pesanan' && doc.status !== 'batal') {
          emit(doc.id_pelanggan, doc.total);
        }
      }",
      "reduce": "_sum"
    },
    "produk_per_kategori": {
      "map": "function(doc) {
        if (doc.tipe === 'produk') {
          emit([doc.kategori, doc.harga], doc.nama_produk);
        }
      }"
    }
  }
}

Query Views

Bash — Query Views (cURL)
# Query view: pelanggan per kota
curl "http://localhost:5984/toko_online/_design/toko/_view/pelanggan_per_kota" \
  -u admin:password123

# Filter berdasarkan key
curl "http://localhost:5984/toko_online/_design/toko/_view/pelanggan_per_kota?key=%22Jakarta%22" \
  -u admin:password123

# Range query
curl "http://localhost:5984/toko_online/_design/toko/_view/pelanggan_per_kota?startkey=%22A%22&endkey=%22M%22" \
  -u admin:password123

# Query reduce: jumlah pelanggan per kota
curl "http://localhost:5984/toko_online/_design/toko/_view/jumlah_pelanggan_per_kota?group=true" \
  -u admin:password123

# Total belanja per pelanggan
curl "http://localhost:5984/toko_online/_design/toko/_view/total_belanja_per_pelanggan?group=true" \
  -u admin:password123

# Include documents (join-like)
curl "http://localhost:5984/toko_online/_design/toko/_view/pelanggan_per_kota?include_docs=true&limit=10" \
  -u admin:password123

7. Mango Queries (Find)

Mango Query (disebut juga _find) adalah cara query yang lebih intuitif daripada MapReduce Views. Mirip dengan MongoDB query syntax.

Bash — Mango Queries
# Cari semua pelanggan di Jakarta
curl -X POST http://localhost:5984/toko_online/_find \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{
    "selector": {
      "tipe": "pelanggan",
      "kota": "Jakarta",
      "is_active": true
    },
    "fields": ["_id", "nama", "email", "kota"],
    "sort": [{"nama": "asc"}],
    "limit": 20
  }'

# Query dengan operator: $gt, $lt, $in, $regex
curl -X POST http://localhost:5984/toko_online/_find \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{
    "selector": {
      "tipe": "produk",
      "$and": [
        {"harga": {"$gte": 100000}},
        {"harga": {"$lte": 5000000}},
        {"stok": {"$gt": 0}}
      ],
      "kategori": {"$in": ["Elektronik", "Fashion"]}
    },
    "sort": [{"harga": "asc"}],
    "limit": 50
  }'

# Text search dengan $regex
curl -X POST http://localhost:5984/toko_online/_find \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{
    "selector": {
      "tipe": "pelanggan",
      "nama": {"$regex": "(?i)budi"}
    }
  }'

Mango Index

Bash — Mango Index
# Buat index untuk performa query
curl -X POST http://localhost:5984/toko_online/_index \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{
    "index": {
      "fields": ["tipe", "kota", "is_active"]
    },
    "name": "idx_pelanggan_kota",
    "type": "json"
  }'

# Compound index untuk sorting
curl -X POST http://localhost:5984/toko_online/_index \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{
    "index": {
      "fields": ["tipe", "kategori", "harga"]
    },
    "name": "idx_produk_kategori_harga",
    "type": "json"
  }'

# Lihat semua index
curl http://localhost:5984/toko_online/_index \
  -u admin:password123

# Explain query (lihat execution plan)
curl -X POST http://localhost:5984/toko_online/_explain \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{
    "selector": {
      "tipe": "pelanggan",
      "kota": "Jakarta"
    }
  }'

8. Clustering & Sharding

CouchDB 3.x mendukung clustering built-in — data di-shard ke beberapa node dan setiap shard di-replicate ke beberapa node untuk redundansi.

Konsep Clustering

KonsepDeskripsiDefault
Shards (Q)Jumlah partisi database8
Replicas (N)Jumlah salinan setiap shard3
Write Quorum (W)Node yang harus konfirmasi write2
Read Quorum (R)Node yang harus setuju saat read2
Bash — Clustering Setup
# =============================================
# 3-Node Cluster Setup
# =============================================

# Node 1 (seed)
docker run -d --name couch1 -e COUCHDB_USER=admin \
  -e COUCHDB_PASSWORD=password123 \
  --net=couchnet --net-alias=couch1 \
  -p 5984:5984 apache/couchdb:3.3

# Node 2
docker run -d --name couch2 -e COUCHDB_USER=admin \
  -e COUCHDB_PASSWORD=password123 \
  --net=couchnet --net-alias=couch2 \
  -p 5985:5984 apache/couchdb:3.3

# Node 3
docker run -d --name couch3 -e COUCHDB_USER=admin \
  -e COUCHDB_PASSWORD=password123 \
  --net=couchnet --net-alias=couch3 \
  -p 5986:5984 apache/couchdb:3.3

# Join node 2 ke cluster
curl -X POST http://localhost:5984/_cluster_setup \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{"action":"enable_cluster","username":"admin","password":"password123","bind_address":"0.0.0.0","port":5984}'

curl -X POST http://localhost:5984/_cluster_setup \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{"action":"add_node","username":"admin","password":"password123","host":"couch2","port":5984}'

# Finish cluster setup
curl -X POST http://localhost:5984/_cluster_setup \
  -H "Content-Type: application/json" \
  -u admin:password123 \
  -d '{"action":"finish_cluster"}'

# Cek cluster membership
curl http://localhost:5984/_membership \
  -u admin:password123

9. Use Cases & Best Practices

Ideal Use Cases untuk CouchDB

Use CaseMengapa CouchDB Cocok
Mobile Apps (offline-first)PouchDB di device + sync saat online
CRM / Sales ToolsSales bisa input data di lapangan tanpa internet
Content ManagementDocument model cocok untuk artikel, halaman
IoT Data CollectionDevice mengumpulkan data offline, sync ke server
Collaborative AppsMulti-user edit dengan conflict resolution
Distributed SystemsMulti-master di beberapa lokasi geografis

Best Practices

PraktikPenjelasan
Gunakan prefix untuk _idMisal "pelanggan_001" agar mudah di-identify
Buat index untuk Mango queriesTanpa index, Mango query scan semua documents
Design documents di version controlViews adalah bagian dari kode, bukan database manual
Compact database secara berkalaCouchDB menyimpan semua revisi, perlu di-compact
Gunakan filtered replicationJangan sync semua data ke mobile, hanya yang relevan
Handle conflict di aplikasiCouchDB mendeteksi conflict, tapi resolusi di sisi app
Bash — Maintenance Commands
# Compact database (hapus revisi lama)
curl -X POST http://localhost:5984/toko_online/_compact \
  -H "Content-Type: application/json" \
  -u admin:password123

# Compact design documents
curl -X POST http://localhost:5984/toko_online/_compact/app \
  -H "Content-Type: application/json" \
  -u admin:password123

# View cleanup (hapus view indexes yang tidak dipakai)
curl -X POST http://localhost:5984/toko_online/_view_cleanup \
  -u admin:password123

# Cek database info
curl http://localhost:5984/toko_online \
  -u admin:password123

# Active tasks (replication, compaction, indexing)
curl http://localhost:5984/_active_tasks \
  -u admin:password123

10. Quiz Pemahaman

📝 Quiz: Apache CouchDB
  1. Apa fungsi field _rev pada document CouchDB?
    Jawaban: Revision tracking — setiap perubahan document menghasilkan _rev baru. Diperlukan untuk update/delete dan untuk mendeteksi conflict saat replication.
  2. Apa perbedaan Views dan Mango Queries?
    Jawaban: Views menggunakan MapReduce (JavaScript functions), hasilnya diindeks. Mango Queries mirip MongoDB syntax (_find), lebih mudah tapi perlu index terpisah.
  3. Apa keunggulan multi-master replication?
    Jawaban: Setiap node bisa menerima write — cocok untuk distributed/offline-first apps. Tidak ada single point of failure seperti primary-replica.
  4. Bagaimana CouchDB menangani conflict?
    Jawaban: CouchDB menyimpan semua revisi dalam revision tree. Saat conflict (dua perubahan pada revisi yang sama), app harus memilih versi mana yang valid.
  5. Kapan sebaiknya TIDAK menggunakan CouchDB?
    Jawaban: Untuk aplikasi yang butuh complex JOIN, transaksi ACID yang ketat, atau analitik relational. CouchDB lebih cocok untuk document-centric dan distributed apps.
🎯 Langkah Selanjutnya

Pelajari TimescaleDB untuk time-series data di PostgreSQL, atau Database Sharding untuk strategi skalabilitas horizontal pada database relasional.