This page explains how a Couchbase cluster is organised, what happens on a write, how to query documents with SQL++, and where it fits relative to other document stores.
Couchbase is a distributed document database that emerged from the 2011 merger of Membase (built on Memcached) and CouchOne (CouchDB). It combines memcached-compatible caching with JSON-document storage, SQL-style querying via N1QL, full-text search, and analytics — all in one cluster. Couchbase positions itself as a multi-model platform competing with MongoDB on operational document workloads while bringing built-in caching and a SQL-first query language.
Couchbase splits functionality into services (Data, Query, Index, Search, Analytics, Eventing) that can run on separate nodes and scale independently, which Couchbase calls multi-dimensional scaling. Each bucket is hashed into 1024 vBuckets; the cluster map tells clients which node holds the active copy of each vBucket, so SDKs talk directly to the right node with no proxy. Buckets contain scopes, and scopes contain collections, which play roughly the role of schemas and tables.
By default a write is acknowledged once the active node has it in memory, which is why Couchbase key-value latency is often sub-millisecond. Persistence to disk and replication happen asynchronously. Applications that cannot tolerate losing an acknowledged write request a durability level: MAJORITY, MAJORITY_AND_PERSIST_TO_ACTIVE, or PERSIST_TO_MAJORITY, trading latency for safety. The Database Change Protocol (DCP) streams mutations to the index, search and analytics services and to cross-datacenter replication.
from datetime import timedelta
from couchbase.auth import PasswordAuthenticator
from couchbase.cluster import Cluster
from couchbase.options import ClusterOptions
cluster = Cluster("couchbase://localhost",
ClusterOptions(PasswordAuthenticator("app", "secret")))
cluster.wait_until_ready(timedelta(seconds=10))
coll = cluster.bucket("shop").scope("inventory").collection("products")
coll.upsert("p::1001", {"type": "product", "name": "Kettle", "price": 39, "tags": ["kitchen"]})
print(coll.get("p::1001").content_as[dict])
rows = cluster.query(
"SELECT p.name, p.price FROM shop.inventory.products p "
"WHERE ANY t IN p.tags SATISFIES t = $tag END ORDER BY p.price",
tag="kitchen")
for r in rows:
print(r)CREATE INDEX idx_tags ON shop.inventory.products(DISTINCT ARRAY t FOR t IN tags END);Key-value operations (get, upsert) bypass the query service entirely and are the fastest path. SQL++ queries need a supporting secondary index; without one they fail or fall back to a primary-index scan.
| Need | Couchbase | Alternative |
|---|---|---|
| Low-latency KV plus flexible JSON queries | Strong fit | MongoDB + Redis |
| Offline-first mobile sync | Couchbase Lite + Sync Gateway | CouchDB / PouchDB |
| Complex multi-document transactions | Supported, with overhead | Relational DB |
| Small single-node app | Heavy to operate | PostgreSQL JSONB, MongoDB |
Document key design deserves the same attention as a primary key in a relational schema. Prefixing keys with the document type (p::1001, order::2026-0001) keeps key-value access simple and readable. Embedding related data that is read together (an order and its line items) avoids extra round trips, while data that changes independently or grows without bound (comments, events) belongs in separate documents that reference each other by key.