Skip to content

AxonOps — AI-Native Control Plane for Open Source Data Platforms

Cassandra Query Consistency Levels

Consistency in Cassandra is tunable—the number of replicas that must acknowledge reads and writes is configurable per operation. This flexibility allows trading consistency for availability and latency.

Quick Reference

For a quick lookup of all consistency levels, quorum calculations, and decision tables, see Consistency Levels Reference.


Unlike traditional databases where consistency is a system property, Cassandra allows specifying consistency per statement.

In cqlsh, consistency is set as a session command:

-- cqlsh session command (not standard CQL)
CONSISTENCY QUORUM;
INSERT INTO orders (id, amount) VALUES (uuid(), 100.00);

In application code, consistency is set via driver API:

// Java Driver example
session.execute(statement.setConsistencyLevel(ConsistencyLevel.QUORUM));

Different operations can be optimized differently within the same application.


Every client request goes to a coordinator node, which manages the consistency guarantee:

Coordinator Processing a Write RequestCoordinator Processing a Write RequestCoordinator Node1. Parse request2. Calculate token3. Look up replicas4. Send to ALL replicas5. Wait for QUORUM6. Return successClientReplica 1ACKReplica 2ACKReplica 3... writingINSERT with CL=QUORUMwritewritewrite

For writes, a replica acknowledges after:

  1. Writing to commit log (durability)
  2. Writing to memtable (memory)

The data is not necessarily flushed to SSTable yet, but it is durable because of the commit log.

For reads, a replica acknowledges by returning its data.


ANY Consistency - Hinted HandoffANY Consistency - Hinted HandoffAll Replicas DownN1N2N3CoordinatorHint Storagewrite (fails)write (fails)write (fails)store hintlater delivery

Data Loss Risk

If the coordinator is permanently lost before delivering the hint, the data may be lost. Hints are durable on the coordinator but require the coordinator to survive. Use ANY only for truly non-critical data.

When to use: Almost never. Only for truly non-critical data where losing some writes is acceptable.

ONE Consistency - Single Replica ACKONE Consistency - Single Replica ACKCoordinatorClientN1N2N3writeACKwrite (async)write (async)SUCCESS

RF = 3, ONE requires 1 ACK. Other replicas receive the write asynchronously.

When to use:

  • High-throughput writes where some inconsistency is acceptable
  • Time-series data with many writes per second
  • When combined with ALL reads (R + W > N)
RFQUORUMFormula
32floor(3/2) + 1
53floor(5/2) + 1
74floor(7/2) + 1

Majority significance:

QUORUM Overlap Guarantees ConsistencyQUORUM Overlap Guarantees ConsistencyWrite QUORUMRead QUORUMABCABCWritten to A, BRead from B, CB has the writeOVERLAP

With RF=3, QUORUM=2: Write to {A, B}, Read from {B, C}. The overlap (B) guarantees the read sees the write.

Multi-datacenter QUORUM:

QUORUM is calculated across the total replication factor of all datacenters combined. This has significant implications for multi-DC deployments.

Multi-DC QUORUM (Total RF=6, QUORUM=4)Multi-DC QUORUM (Total RF=6, QUORUM=4)DC1 (RF=3)DC2 (RF=3)ABCDEFCoordinator4 ACKs from any replicas(3 from DC1 + 1 from DC2)ACKACKACKACK (cross-DC)

With 2 DCs and RF=3 per DC: Total RF = 6, QUORUM = 4. Unlike EACH_QUORUM, QUORUM can be satisfied with any 4 replicas regardless of DC distribution (e.g., 3 from DC1 + 1 from DC2).

When to use:

  • Global strong consistency is a hard requirement
  • Can tolerate cross-DC latency on every operation
  • Regulatory or compliance requirements for synchronous cross-DC writes

LOCAL_QUORUM: Majority in Local Datacenter

Section titled “LOCAL_QUORUM: Majority in Local Datacenter”
LOCAL_QUORUM - Only Wait for Local DCLOCAL_QUORUM - Only Wait for Local DCDC1 - Coordinator HereDC2 - RemoteABCDEFCoordinatorClientwrite + waitACKwrite + waitACKasync (no wait)async (no wait)SUCCESS

2 ACKs from DC1 = SUCCESS. Data is still sent to DC2, but coordinator does not wait.

Latency Advantage

ConsistencyPathTypical Latency
QUORUM (multi-DC)Client → DC1 → DC2 → DC1 → Client50-200ms
LOCAL_QUORUMClient → DC1 → Client1-5ms

LOCAL_QUORUM is significantly faster for multi-DC deployments by avoiding cross-DC latency.

When to use: Multi-DC deployments (almost always the right choice).

EACH_QUORUM - Quorum Required in Every DCEACH_QUORUM - Quorum Required in Every DCDC1DC2ABCDEFCoordinatorClientMust wait for slowest DCmust get quorum2/3 ACKmust get quorum2/3 ACKSUCCESS

Must wait for the slowest DC to achieve quorum.

When to use:

  • Regulatory requirements for cross-DC consistency
  • Financial transactions that must be in all regions before acknowledgment
  • Rare—most applications do not need this
ALL Consistency - Every Replica Must ACKALL Consistency - Every Replica Must ACKCoordinatorN1N2N3writeACKwriteACKwriteACK

Availability Risk

If any replica is down, the write fails. Single node failure causes complete write unavailability.

When to use: Almost never for writes. Single node failure causes all writes to fail.


ONE Read - Fastest but Possibly StaleONE Read - Fastest but Possibly StaleClientCoordinatorN1N2ClientClientCoordinatorCoordinatorN1N1N2N2Read requestReadData (possibly stale)Return dataN2, N3 not contacted

If N1 has stale data, stale data is returned. Background read repair may fix inconsistency later.

QUORUM Read - Compare TimestampsQUORUM Read - Compare TimestampsClientCoordinatorN1N2ClientClientCoordinatorCoordinatorN1N1N2N2Read request (QUORUM)ReadReadData (ts=1000)Data (ts=2000)Compare timestampsReturn newest (ts=2000)Data (ts=2000)Trigger read repair for N1

Coordinator returns the newest data based on timestamp. If replicas disagree, coordinator triggers read repair.

Same logic as QUORUM, but only contacts local DC replicas. Provides strong consistency within the datacenter with lower latency.

Note

EACH_QUORUM is write-only. For reads, use QUORUM (for cross-DC consistency) or LOCAL_QUORUM (for local consistency).

ALL Read - Any Failure Causes TimeoutALL Read - Any Failure Causes TimeoutClientCoordinatorN1N2N3ClientClientCoordinatorCoordinatorN1N1N2N2N3N3Read request (ALL)ReadReadReadDataDataTimeout/DownTIMEOUT ERROR

Warning

If any replica is down or slow, the read times out.

When ALL reads make sense:

  • Combined with ONE writes (R + W > N)
  • Read-heavy workload where fast writes are desired
  • Single node failure causes all reads to fail

A common heuristic for strong consistency:

R = Number of replicas read
W = Number of replicas written
N = Replication factor
If R + W > N, there is at least one replica overlap between reads and writes.

Heuristic, Not Guarantee

R + W > N provides overlap between read and write replicas but does not account for concurrent writes, hinted handoff, or clock skew. It is a useful heuristic, not a strict guarantee of linearizability.

Why it works:

N = 3 (three replicas total)
W = 2 (write to two replicas)
R = 2 (read from two replicas)
R + W = 4 > 3 = N
The sets of written replicas and read replicas MUST overlap.
Write went to: {A, B}
Read contacts: {B, C}
Overlap: B ← Has the write
CombinationR + WStrong?Use Case
W=QUORUM, R=QUORUM4 > 3YesStandard strong consistency
W=ONE, R=ALL4 > 3YesWrite-heavy, few reads
W=ALL, R=ONE4 > 3YesRead-heavy, few writes
W=LOCAL_QUORUM, R=LOCAL_QUORUM4 > 3 per DCYes (per DC)Multi-DC standard
W=ONE, R=ONE2 < 3NoHigh throughput, eventual
W=ONE, R=QUORUM3 = 3No*Sometimes inconsistent

*R + W = N is not sufficient; must be strictly greater than.

ConfigurationQUORUMLOCAL_QUORUM
DC1: RF=3, DC2: RF=34 (global)2 (per DC)
Write behavior4 replicas (any DC)2 replicas (local DC only)
Read behavior4 replicas (any DC)2 replicas (local DC only)
ConsistencyGlobalPer-DC (cross-DC eventual)

For most applications, LOCAL_QUORUM is sufficient because cross-DC replication happens in milliseconds.


RF=3, One Node DownRF=3, One Node DownClusterABCNode down
CLWorks?Reason
ONE2 replicas available
QUORUM (2)2 of 3 available
ALLC is down
RF=3, Two Nodes DownRF=3, Two Nodes DownClusterABCNodes down
CLWorks?Reason
ONE1 replica available
QUORUM (2)Only 1 of 3 available
ALLB and C down
Six replicas across two datacenters with all three DC2 replicas unavailableSix replicas across two datacenters with all three DC2 replicas unavailableDC1 (UP)DC2 (DOWN)ABCDEFEntire DC down
CLWorks?Reason
LOCAL_ONEOnly needs local DC
LOCAL_QUORUMOnly needs local DC
QUORUM (4/6)Only 3 of 6 available
EACH_QUORUMDC2 has no quorum

Key Insight

LOCAL_QUORUM survives entire DC failure while maintaining strong local consistency. This is why it is recommended for multi-DC deployments.


For operations requiring linearizable consistency (compare-and-set semantics), Cassandra provides Lightweight Transactions using the Paxos consensus algorithm.

-- Compare-and-set with IF clause triggers LWT
UPDATE account SET balance = 50 WHERE id = 1 IF balance = 100;
-- Returns [applied] = true if balance was 100
-- Returns [applied] = false if balance was different
Serial CLScopeUse Case
SERIALAll DCsGlobal uniqueness
LOCAL_SERIALLocal DCDC-local uniqueness

Performance Impact

LWTs require 4 round trips (vs 1 for regular writes), resulting in 4-10x higher latency. Use only when compare-and-set semantics are required.

Consensus and Paxos for detailed coverage of LWT internals, Paxos v1 vs v2, best practices, and the upcoming Accord protocol.


Speculative execution sends duplicate requests to reduce tail latency when one replica is slow.

When one replica is slow (e.g., due to GC pause), the client must wait for it:

Without Speculative ExecutionWithout Speculative ExecutionClientCoordinatorN1 .fast.N2 .slow.ClientClientCoordinatorCoordinatorN1 (fast)N1 (fast)N2 (slow)N2 (slow)QUORUM read (need 2 of 3)Read requestT+0msReadReadT+5msResponseHave 1, need 2...waitingGC pauseT+500msResponse (delayed)Return resultTotal latency: 500ms

When a replica exceeds the expected latency threshold, the coordinator sends a speculative request to another replica:

With Speculative ExecutionWith Speculative ExecutionClientCoordinatorN1 .fast.N2 .slow.N3 .fast.ClientClientCoordinatorCoordinatorN1 (fast)N1 (fast)N2 (slow)N2 (slow)N3 (fast)N3 (fast)QUORUM read (need 2 of 3)Read requestT+0msReadReadT+5msResponseT+10ms: N2 exceeds 99th percentileSpeculative readT+15msResponseHave 2 responses (N1, N3)Return resultTotal latency: 15msStill processing...ignored
ScenarioLatency
Without speculative execution500ms (waiting for slow N2)
With speculative execution15ms (N3 responds instead)
-- Per-table speculative retry setting
ALTER TABLE users WITH speculative_retry = '99percentile';
-- Options:
-- 'Xpercentile': Retry after X percentile latency
-- 'Yms': Retry after Y milliseconds
-- 'ALWAYS': Always send to extra replica immediately
-- 'NONE': Disable speculative retry

Trade-off: Speculative execution increases replica load but reduces tail latency.


Diagnosis steps:

  1. Check consistency levels: Write CL + Read CL > RF?
  2. Check for clock skew: chronyc tracking (or ntpq -p) on each node, and compare the offsets across nodes rather than reading each in isolation. See Monitoring time synchronization for what the output means and what skew does to last-write-wins.
  3. Check for failed writes: Application logs for timeouts
  4. Enable tracing: TRACING ON;
TRACING ON;
SELECT * FROM users WHERE user_id = 123;
-- Output shows:
-- - Which replicas were contacted
-- - Response times from each
-- - Whether read repair occurred
# Unavailable errors (CL could not be satisfied)
org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Unavailables
org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Unavailables
# Timeouts
org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Timeouts
org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Timeouts
# LWT metrics
org.apache.cassandra.metrics:type=ClientRequest,scope=CASWrite,name=Latency
org.apache.cassandra.metrics:type=ClientRequest,scope=CASWrite,name=ContentionHistogram

ScenarioWrite CLRead CLRationale
Single DC, strong consistencyQUORUMQUORUMR+W > N
Multi-DC, low latencyLOCAL_QUORUMLOCAL_QUORUMNo cross-DC wait
Multi-DC, global consistencyQUORUMQUORUMCross-DC consensus
High throughput, eventual OKONEONEFastest
Write-heavyONEALLFast writes
Read-heavyALLONEFast reads
Time-series metricsLOCAL_ONELOCAL_ONEVolume over consistency
MistakeConsequence
Using ALL in productionSingle node failure breaks everything
QUORUM in multi-DC when LOCAL_QUORUM sufficesUnnecessary latency
ONE/ONE without understandingNo consistency guarantee
Overusing LWTPerformance degradation
Ignoring clock skewSilent data loss via timestamp conflicts
MetricAlert ThresholdMeaning
Unavailables>0CL cannot be met
Timeouts>1%Replicas too slow
Read repair rate>10%High inconsistency
LWT contention>10%Redesign needed