cswork / libraryOpen practice workspace

Articles

Couchbase Interview Questions: vBuckets, Consistency, and Query Indexes

Explain Couchbase vBuckets, query consistency, mutation tokens, durability, CAS updates, and covering indexes through worked interview exercises.

You update an order in Couchbase, receive a successful write response, and immediately run a SQL++ query. The order is missing from the result. Does that prove the write failed? A useful interview answer distinguishes the data service from the query index before suggesting a retry.

Couchbase interview questions become clearer when you separate four contracts: where a document lives, when a query can see it, which failures a write acknowledgment covers, and whether a concurrent update can overwrite your change. This article uses an original order timeline and query-index exercise to make those contracts observable.

Official facts are linked to current Couchbase Server and Python SDK documentation. Examples, predictions, and diagnostic recommendations are original practice or inference. No candidate reports are used, and these exercises do not establish an employer's interview format. Practice the larger partitioning decision with Scale a key-value store with consistent hashing.

What is a vBucket, and how does a client find a document?

Official fact: Couchbase partitions a bucket into vBuckets. A key is hashed to a vBucket, and a client uses the cluster's vBucket map to find the node holding its active copy. Replica copies are placed on different nodes. See the vBucket documentation.

Explain the two mappings separately: document key to logical partition, then logical partition to node. Adding a node changes ownership and distribution during rebalance; it does not mean the application should invent a new key-to-node formula. Explain how the SDK receives and uses updated topology information.

Avoid turning a remembered partition count into a universal guarantee. Official fact: current documentation distinguishes Couchstore, Magma, and macOS: Linux and Windows Couchstore buckets use 1024 vBuckets; Magma can use 128 or 1024; macOS uses 64. The chosen bucket count is fixed after creation. Identify the deployment before quoting a number.

For an original thought experiment, imagine eight logical partitions distributed across three nodes. You can move partition ownership to a fourth node without changing which logical partition contains order::42. Eight is a teaching fixture, not a supported configuration claim.

Ask what happens if a node holding an active partition fails. A replica may be promoted through the cluster's failover process, and clients need the new map. Then ask a different question: which acknowledged mutations are guaranteed to survive that failure? Partition ownership alone cannot answer it. That is where the configured durability requirement matters.

An even key distribution also does not prove an even workload. A single popular key can concentrate requests despite many partitions. In an interview, distinguish the count of stored documents from request rate, object size, and the cost of operations on those documents.

Why can a KV read and a SQL++ query disagree?

Official fact: query scan consistency defaults to NOT_BOUNDED in the Python SDK. A query can use the index's existing state without waiting for recent mutations. REQUEST_PLUS asks for the index to catch up to the request's consistency boundary. A mutation state can narrow that requirement to particular writes. The SDK query documentation describes these options.

Now follow this original timeline. Assume the write has succeeded and no later writer changes the document:

MomentData serviceQuery indexWhat the observation establishes
T0order::42 is pendingPending entryInitial state
T1Successful update sets paidStill pendingWrite success under its selected acknowledgment contract
T2Active KV read returns paidStill pendingDirect document read sees the updated value
T3No further document changeIndex catches up to paidIndexed predicate can now discover it

At T2, WHERE status = "paid" can omit the order under an index-backed, not-bounded query. That is consistent with the assumed lag. The key detail is the access path: “Couchbase read” is too vague when one read is by key and another discovers keys through an index.

This explanation does not mean every missing result is index lag. The query might address the wrong collection, apply another predicate, or exclude the document because a value is missing or has a different type. State the hypothesis and inspect the actual document and statement before changing consistency globally.

The exercise also assumes no deletion, expiration, or concurrent status change. In a real investigation, record the document key, mutation time, relevant fields, query parameters, and consistency option. Otherwise, you may compare observations from different states and attribute the disagreement to the database incorrectly.

Which consistency setting would you choose?

A helpful answer begins with the user's requirement. An order-confirmation screen may need to read the exact order just written. A discovery page may need a query to include several writes from the same workflow. A monitoring view may tolerate a short index lag in exchange for less waiting.

For the first case, a key-based read can avoid rediscovering a known document through a secondary index. For the second, a mutation-state consistency requirement expresses which completed writes must be included. REQUEST_PLUS is useful when the request needs a broader current boundary rather than a token set for selected mutations.

Those are design recommendations, not a promise that one setting is always fastest. Measure index lag and wait time under the relevant load. A setting that waits for freshness may expose slow index maintenance rather than remove it.

Here is an SDK-shaped practice fragment, assuming an authenticated cluster and collection already exist:

from couchbase.mutation_state import MutationState
from couchbase.options import QueryOptions

written = collection.upsert("order::42", {
    "tenant": "north",
    "status": "paid",
    "amount": 120
})
state = MutationState(written)
result = cluster.query(
    "SELECT o.amount FROM `shop`.sales.orders AS o "
    "WHERE o.tenant = $tenant AND o.status = $status",
    QueryOptions(
        named_parameters={"tenant": "north", "status": "paid"},
        consistent_with=state
    )
)
rows = list(result.rows())

Verify the SDK version and mutation-token configuration in a real deployment. The example is documentation-aligned practice, not an integration test against a running cluster.

Do not describe the freshness boundary as a permanent lock on the world. Another writer can still act. Nor does waiting for an index create an atomic invariant across several independent reads and writes. If the workflow needs transactional behavior, say so explicitly and evaluate the corresponding transaction contract.

How are consistency, durability, and CAS different?

Official fact: the data operations documentation exposes durability choices and compare-and-swap behavior. CAS represents a document version for optimistic concurrency: supply the value you read when replacing the document, and handle a version mismatch rather than overwriting blindly.

Consider two workers reading an order with attempts = 4. Each independently calculates 5. If both replace the entire document without a concurrency condition, the final value can be 5 although two attempts happened. Making the later SQL++ query wait for index freshness does not recover the lost increment.

With CAS, the second replace against the obsolete version fails. The worker then reads the current document and re-evaluates its intended operation. If its update remains valid, it computes 6 and attempts another conditional replace. Bound retries and report unresolved contention rather than spin indefinitely.

Re-evaluation matters when the mutation is more than arithmetic. Suppose a worker wants to cancel an order only while it is pending. On retry, the current state may be paid. Reapplying the old replacement would violate the business rule even if a fresh CAS token makes the write technically acceptable.

Durability addresses a different question: which replication or persistence conditions must be satisfied before a write counts as successful? Stronger durability does not make an asynchronous query index instantly current. CAS does not, by itself, establish a desired persistence level. Query freshness does not prevent a competing writer from changing the document.

In an interview, answer with a three-part contract: “The mutation uses this durability requirement; the update is conditional on this document version; the following query needs this scan-consistency boundary.” Each clause can be tested independently.

What makes an index useful rather than merely present?

Official fact: a covering index contains the values a query needs so that its plan can avoid fetching the full document for those values. Couchbase's covering-index documentation shows how EXPLAIN exposes coverage.

Use this original SQL++ exercise:

CREATE INDEX orders_by_tenant_status_time
ON `shop`.sales.orders(tenant, status, created_at, amount);

EXPLAIN
SELECT o.created_at, o.amount
FROM `shop`.sales.orders AS o
WHERE o.tenant = "north"
  AND o.status = "paid"
  AND o.created_at >= "2026-09-01T00:00:00Z"
  AND o.created_at < "2026-10-01T00:00:00Z";

Assume timestamps are consistently normalized ISO strings in this fixture. Mixing time zones or representations would make a lexical range an unsafe stand-in for the intended chronological range.

Explain the index fields by role: tenant and status constrain the requested subset; creation time bounds the range; amount supplies the selected measure. This is a candidate index to inspect, not a guarantee that the optimizer selects it or that it is optimal for every workload.

Now change the query to select customer_email. Coverage may require a fetch because that value is absent from this index. Selecting the entire document similarly changes the requirement. A useful answer examines the resulting plan rather than counting how many indexes the collection has.

Next, remove the tenant predicate. The access pattern is different, and the same leading-key arrangement may no longer be the right design. Finally, add an ORDER BY and inspect whether the plan satisfies ordering or introduces a sort. Coverage and ordering are separate properties.

Discuss the cost as well. Additional index fields consume storage and require maintenance as documents change. An index that improves one query can increase write work. Choose a small set of representative query shapes and measure their plans and latency before expanding every index into a copy of the document.

How would you investigate a slow or stale result?

Describe a controlled sequence. First, confirm the bucket, scope, collection, key, and parameter values. Read the known document directly. Then inspect the query's consistency option and plan. Separate time waiting for index catch-up from time executing the scan and fetching documents.

If a stricter consistency mode returns the expected row, that supports the lag hypothesis under the tested conditions. It does not prove that every earlier mismatch had the same cause. If both modes omit the row, examine predicates and document shape before retrying the mutation.

For performance, compare the same query and dataset under a bounded workload. Record scanned versus returned data where profiling exposes it, index coverage, fetches, sorting, and the latency distribution. A single fast execution with a warm cache is weak evidence for an index change.

For failover, state the failure being simulated and the write's durability level. Then verify the document and query behavior after the topology change. Keep that experiment separate from the normal read-after-write exercise so the explanation does not mix replication failure with ordinary index lag.

Practice the architecture around these contracts

QuestionCouchbase reasoning to bring to the answer
Scale a key-value store with consistent hashingSeparate logical partition identity from node ownership.
Design a Distributed Key-Value StoreDefine the acknowledgment and read contracts.
High Availability and Failover for a Primary-Replica DatabaseIdentify what promotion does and which writes survive.
Design a replicated key-value store with quorumsExplain replica coordination without conflating it with index visibility.
Architecture and Data-Scaling Trade-offsConnect query shapes to index maintenance cost.

Use the distributed key-value store exercise to explain a successful write, a stale query, and a competing update as three different traces.

Sources and further reading