Choosing the right Couchbase durability level is less about picking a setting and more about defining your application’s tolerance for data loss versus its need for immediate consistency.

Let’s see durability in action. Imagine an e-commerce application where a customer places an order. We’ll simulate this with a simple Python script using the couchbase SDK.

from couchbase.cluster import Cluster
from couchbase.auth import PasswordAuthenticator
from couchbase.options import ClusterOptions, InsertOptions

# Connect to Couchbase
auth = PasswordAuthenticator('Administrator', 'password')
cluster = Cluster('couchbase://localhost', ClusterOptions(auth))
bucket = cluster.bucket('my_bucket')
collection = bucket.default_collection()

# Simulate an order
order_data = {
    "customer_id": "cust_123",
    "items": ["item_A", "item_B"],
    "total": 150.00,
    "status": "pending"
}

# Insert with different durability levels
try:
    # Level: PersistTo.NONE (default, fastest, least durable)
    result_none = collection.insert("order:1", order_data, InsertOptions(durability_level=0))
    print(f"Inserted with NONE durability. Doc ID: {result_none.id}")

    # Level: PersistTo.ACTIVE (data on primary node, fast)
    result_active = collection.insert("order:2", order_data, InsertOptions(durability_level=1))
    print(f"Inserted with ACTIVE durability. Doc ID: {result_active.id}")

    # Level: PersistTo.REPLICA (data on primary + 1 replica, slower, more durable)
    result_replica = collection.insert("order:3", order_data, InsertOptions(durability_level=2))
    print(f"Inserted with REPLICA durability. Doc ID: {result_replica.id}")

    # Level: PersistTo.MAJORITY (data on majority of nodes, slowest, most durable)
    result_majority = collection.insert("order:4", order_data, InsertOptions(durability_level=3))
    print(f"Inserted with MAJORITY durability. Doc ID: {result_majority.id}")

except Exception as e:
    print(f"An error occurred: {e}")

In this example, durability_level maps to Couchbase’s durability settings: 0 for PersistTo.NONE, 1 for PersistTo.ACTIVE, 2 for PersistTo.REPLICA, and 3 for PersistTo.MAJORITY. The key takeaway is that each level represents a trade-off. PersistTo.NONE gives you the quickest write, but if the primary node crashes before the data is replicated or persisted to disk, that write is lost. PersistTo.MAJORITY is the safest, ensuring your data survives even if half your nodes go down, but it introduces latency.

Couchbase’s durability mechanism is built around its master-replica architecture. When you write a document, it first goes to the primary node for that vBucket. The durability level dictates how many acknowledgments the client waits for before considering the write successful.

  • PersistTo.NONE: The client gets an acknowledgment as soon as the primary node accepts the write. No guarantees about persistence.
  • PersistTo.ACTIVE: The client waits for the primary node to persist the data to its local disk. This protects against temporary node restarts but not against node failure if data isn’t flushed.
  • PersistTo.REPLICA: The client waits for confirmation that the data has been persisted to disk on the primary node and at least one replica node. This is a good balance for many applications.
  • PersistTo.MAJORITY: The client waits for confirmation that the data has been persisted to disk on a majority of nodes in the cluster. This provides the highest level of durability.

The choice hinges on your application’s Service Level Agreement (SLA) for consistency and durability. If losing a few recent writes during a catastrophic failure is acceptable in exchange for lower latency (e.g., logging transient events), PersistTo.NONE or PersistTo.ACTIVE might suffice. If every single write must be guaranteed to survive even significant hardware failures, you’ll lean towards PersistTo.REPLICA or PersistTo.MAJORITY. The actual number of replicas configured in your Couchbase bucket settings also plays a role, especially for PersistTo.REPLICA and PersistTo.MAJORITY. For PersistTo.MAJORITY, Couchbase needs (N/2) + 1 nodes to acknowledge the write, where N is the total number of active nodes.

A subtle but critical point is that the durability level only guarantees persistence to disk and replication to a certain number of nodes. It doesn’t guarantee that the data has been flushed from the operating system’s file cache to physical disk. For absolute certainty that data is on physical media, PersistTo.ACTIVE is the minimum, but even then, OS-level caching can introduce a tiny window of risk until a flush occurs.

Once you’ve mastered durability levels, the next natural question is how to handle read consistency and ensure you’re reading the most up-to-date data, especially in distributed systems.

Want structured learning?

Take the full Couchbase course →