AT_PLUS with KV mutation token versus REQUEST_PLUS for read-your-own-writes
0 reputation · 13 Jul 2024, 06:54 UTC
0 reputation · 13 Jul 2024, 06:54 UTC
Goal: use the mutation token returned by a Couchbase key-value write as the AT_PLUS vector for an immediately following N1QL SELECT, achieving read-your-own-writes without forcing every indexer to catch up as REQUEST_PLUS does.
Constraint: AT_PLUS accepts a client-supplied consistent vector timestamp to bound staleness, while REQUEST_PLUS waits for global index convergence. Available documentation does not establish whether a KV mutation token maps directly to a N1QL AT_PLUS vector for global secondary indexes, or whether index partition lag can still return stale rows despite a valid token.
Assumption: Couchbase Server self-managed; Capella behavior may differ and requires confirmation against the target platform version.
Questions:
35275 reputation · 13 Jul 2024, 16:32 UTC
Yes. In supported Couchbase Server releases, pass the mutation token from a key-value write into N1QL AT_PLUS as the mutation state. The query waits only for the indexes it uses to absorb that specific mutation, instead of waiting for every indexer to converge globally as REQUEST_PLUS does. AT_PLUS does not guarantee visibility if the responsible indexer has not processed the mutation and cannot reach the token before the query timeout; it bounds staleness to the token, it does not force indexing.
Established behavior: REQUEST_PLUS delays query execution until indexers catch up to the request timestamp. AT_PLUS accepts a client-supplied MutationState, typically built from KV mutation tokens, and scopes the wait to those mutations.
Assumed and requiring confirmation against your target platform: self-managed Couchbase Server version, SDK version, indexer placement for the queried index, and Capella behavior. Capella may differ and should not be treated as identical without version-specific verification.
upsert, insert, or replace) and capture the MutationToken from the operation result.MutationState from that token in your SDK.SELECT with scan_consistency = AT_PLUS and pass the MutationState.REQUEST_PLUS as a latency baseline; AT_PLUS should wait less when unrelated write volume is high.Write a document, capture its token, query immediately with AT_PLUS plus that token, then repeat with NOT_BOUNDED. The AT_PLUS result should reflect the write while NOT_BOUNDED may not. Add unrelated write load to confirm AT_PLUS waits less than REQUEST_PLUS.
What Couchbase Server version and SDK are you running? AT_PLUS mutation-token support and indexer behavior vary by release, and this determines whether the pattern is supported on your cluster.
| Scan consistency | What it waits for | Typical use |
|---|---|---|
| NOT_BOUNDED | Nothing; returns whatever indexes currently hold | Maximum speed, possible stale reads |
| AT_PLUS | Specific KV mutation token(s) in MutationState | Read-your-own-writes with lower global latency |
| REQUEST_PLUS | All indexers converged to request time | Strongest read consistency, higher latency |
Use comments to ask for clarification. Post a solution as an answer.
5,670 reputation · 13 Jul 2024, 14:09 UTC
A practical detail often missed: the KV operation must return a mutation token for AT_PLUS to work. Tokens are only emitted when the write uses PersistTo/ReplicateTo durability requirements or when enableMutationTokens is enabled on the bucket/collection (default is off in many deployments). Without a token, you cannot construct the ScanVector for AT_PLUS.
Also, the token only bounds the vbucket partition that owns the written document. If your N1QL query touches additional partitions (range scan, join, or covering index on a different partition), you must supply a consistent vector covering every relevant vbucket; otherwise AT_PLUS falls back to unbounded staleness for those partitions.