Chapter 14 · Consistency Levels, Quorums, Availability, and Client Guarantees

Serial Consistency for LWT vs Regular Consistency for Data Operations

Separate Paxos serial consistency for LWT from ordinary data-operation consistency and test conditional contention.

Intermediate100–145 minutesLWT/Paxos contention labApache Cassandra 5.0.9 · Java 17 · cqlsh/nodetool · Java Driver 4.19.3 optional · RF=3 dc1 baselineLast reviewed: September 2026

Learning outcomes

AtlasMart must reserve a scarce product once. A normal INSERT at LOCAL_QUORUM can be highly available, but two concurrent writers can both decide the item is free. The business invariant is compare-and-set, so Cassandra must run a Lightweight Transaction (LWT) using Paxos.

01

Distinguish ordinary consistency from serial consistency in conditional CQL.

02

Explain SERIAL versus LOCAL_SERIAL as Paxos/serial-phase scope and regular CL as the learn/data phase.

03

Run IF NOT EXISTS concurrently and observe one applied result and one rejected condition.

04

Explain why LWT has higher latency and failure sensitivity than an ordinary mutation.

05

Choose LWT only when the business invariant requires linearizable compare-and-set semantics.

Chapter 14 lab baseline

The mandatory single-DC labs use Apache Cassandra 5.0.9 in the pinned Docker image cassandra:5.0.9, Java 17 inside the image, cluster atlasmart-course, network atlasmart-cassandra, nodes atlasmart-cass-1..3, datacenter dc1, racks rack1..rack3, 16 virtual nodes per node, NetworkTopologyStrategy, replication factor (RF) 3, and explicit per-request consistency levels (CLs). New tables use UnifiedCompactionStrategy (UCS), no default Time To Live (TTL), and the Cassandra default gc_grace_seconds unless a lesson states otherwise. Authentication, client Transport Layer Security (TLS), internode TLS, and remote Java Management Extensions (JMX) are disabled only inside the isolated local learning network. The optional application example uses Apache Cassandra Java Driver 4.19.3. Windows learners should use Docker Desktop/WSL-style Linux containers; commands run inside containers unless labeled host-side.

bash · verify or recreate the three-node dc1 lab
docker network inspect atlasmart-cassandra >/dev/null 2>&1 || docker network create atlasmart-cassandradocker volume create atlasmart-cass-1-datadocker volume create atlasmart-cass-2-datadocker volume create atlasmart-cass-3-datadocker inspect atlasmart-cass-1 >/dev/null 2>&1 || docker run -d --name atlasmart-cass-1 --hostname atlasmart-cass-1 --network atlasmart-cassandra -e CASSANDRA_CLUSTER_NAME=atlasmart-course -e CASSANDRA_DC=dc1 -e CASSANDRA_RACK=rack1 -e CASSANDRA_ENDPOINT_SNITCH=GossipingPropertyFileSnitch -e CASSANDRA_NUM_TOKENS=16 -v atlasmart-cass-1-data:/var/lib/cassandra cassandra:5.0.9# Wait until node 1 reports UN before starting peers.docker exec atlasmart-cass-1 nodetool statusdocker inspect atlasmart-cass-2 >/dev/null 2>&1 || docker run -d --name atlasmart-cass-2 --hostname atlasmart-cass-2 --network atlasmart-cassandra -e CASSANDRA_CLUSTER_NAME=atlasmart-course -e CASSANDRA_DC=dc1 -e CASSANDRA_RACK=rack2 -e CASSANDRA_ENDPOINT_SNITCH=GossipingPropertyFileSnitch -e CASSANDRA_NUM_TOKENS=16 -e CASSANDRA_SEEDS=atlasmart-cass-1 -v atlasmart-cass-2-data:/var/lib/cassandra cassandra:5.0.9docker inspect atlasmart-cass-3 >/dev/null 2>&1 || docker run -d --name atlasmart-cass-3 --hostname atlasmart-cass-3 --network atlasmart-cassandra -e CASSANDRA_CLUSTER_NAME=atlasmart-course -e CASSANDRA_DC=dc1 -e CASSANDRA_RACK=rack3 -e CASSANDRA_ENDPOINT_SNITCH=GossipingPropertyFileSnitch -e CASSANDRA_NUM_TOKENS=16 -e CASSANDRA_SEEDS=atlasmart-cass-1 -v atlasmart-cass-3-data:/var/lib/cassandra cassandra:5.0.9# Continue only after all three nodes are UN.docker exec atlasmart-cass-1 nodetool statusdocker exec atlasmart-cass-1 nodetool versiondocker exec atlasmart-cass-1 java -versiondocker exec atlasmart-cass-1 cqlsh -e "SHOW VERSION"
CQL · Chapter 14 single-DC fixture
CREATE KEYSPACE IF NOT EXISTS atlasmart_consistencyWITH replication = {'class':'NetworkTopologyStrategy','dc1':3};CREATE TABLE IF NOT EXISTS atlasmart_consistency.order_status_by_id (    order_id text PRIMARY KEY,    status text,    version int,    updated_at timestamp) WITH compaction = {'class':'UnifiedCompactionStrategy'};CREATE TABLE IF NOT EXISTS atlasmart_consistency.inventory_reservation_by_product (    product_id text,    reservation_id text,    customer_id text,    state text,    created_at timestamp,    PRIMARY KEY (product_id, reservation_id)) WITH compaction = {'class':'UnifiedCompactionStrategy'};CONSISTENCY LOCAL_QUORUM;INSERT INTO atlasmart_consistency.order_status_by_id(order_id,status,version,updated_at)VALUES ('order-42','PAID',1,toTimestamp(now()));DESCRIBE KEYSPACE atlasmart_consistency;
Execution and safety note

Run commands only against the disposable Apache Cassandra course lab or another explicitly approved non-production environment. Confirm node, keyspace, table, container, volume, path, and datacenter targets before destructive, failure-injection, cleanup, repair, restore, security, or topology operations. Capture current state and expected rollback/recovery evidence first; output and timings can differ by host, operating system, Java runtime, Docker/runtime, driver, and Cassandra configuration.

Core terms used throughout this chapter

Replication factor (RF) is the number of replicas Cassandra is configured to keep for each partition in a datacenter. A replica stores a copy of a partition; the coordinator is the node handling one client request and is not a permanent leader. A consistency level (CL) is the per-request rule that says how many and which replicas must acknowledge a write or satisfy a read before the coordinator can return success. A datacenter (DC) is Cassandra's logical locality/failure-domain grouping; a rack is a smaller placement grouping within a DC. A quorum is a majority, calculated as floor(RF/2)+1 for the relevant replica scope. CQL means Cassandra Query Language; cqlsh is its shell. A Lightweight Transaction (LWT) is a conditional CQL operation using Paxos consensus; it has a serial phase and a regular learn/data phase. Availability here means whether enough replicas are alive/responding for the requested CL—not whether the cluster has any node alive. Staleness means a read can return an older replica version because the requested read CL did not necessarily intersect the replicas that acknowledged a prior write.

1. LWT has two consistency dimensions

A conditional statement such as INSERT ... IF NOT EXISTS is not an ordinary last-write-wins mutation. Cassandra uses Paxos to establish a single linearizable order for competing conditional operations. Serial consistency controls the Paxos/serial phase: SERIAL spans the relevant replicas globally, while LOCAL_SERIAL limits the serial quorum to the local DC. The normal consistency setting still controls the learn/data phase and what normal reads are guaranteed to observe immediately after a successful LWT.

Setting Used for Typical choice in local-DC service What it does not mean
SERIAL CONSISTENCY LOCAL_SERIAL Paxos phase of IF conditions serial quorum in local DC not the same as regular LOCAL_QUORUM
CONSISTENCY LOCAL_QUORUM learn/data phase and ordinary operations local majority does not make a non-conditional write an LWT
SERIAL global serial phase use only if invariant scope requires it not a general read/write CL shortcut
LOCAL_SERIAL DC-local serial phase reduces cross-DC dependency does not isolate tenants or authorize callers

2. Run a conditional reservation

CQL · first reservation attempt
CONSISTENCY LOCAL_QUORUM;SERIAL CONSISTENCY LOCAL_SERIAL;INSERT INTO atlasmart_consistency.inventory_reservation_by_product(product_id,reservation_id,customer_id,state,created_at)VALUES ('sku-9','slot-1','customer-A','HELD',toTimestamp(now()))IF NOT EXISTS;SELECT * FROM atlasmart_consistency.inventory_reservation_by_productWHERE product_id='sku-9' AND reservation_id='slot-1';

The expected first result contains [applied] = True. A competing conditional insert for the same primary key should return [applied] = False and expose the current values, rather than silently overwriting them.

CQL · competing reservation attempt
CONSISTENCY LOCAL_QUORUM;SERIAL CONSISTENCY LOCAL_SERIAL;INSERT INTO atlasmart_consistency.inventory_reservation_by_product(product_id,reservation_id,customer_id,state,created_at)VALUES ('sku-9','slot-1','customer-B','HELD',toTimestamp(now()))IF NOT EXISTS;

3. Make concurrency visible

Open two terminals and execute the two conditional inserts as close together as possible after deleting the probe row. Exactly one should win the condition. The exact ordering, trace messages, and latency are nondeterministic. Enable tracing for one run to see the extra Paxos work, but do not treat one localhost timing as an LWT performance benchmark.

CQL · reset and trace one LWT
CONSISTENCY LOCAL_QUORUM;DELETE FROM atlasmart_consistency.inventory_reservation_by_productWHERE product_id='sku-9' AND reservation_id='slot-1';SERIAL CONSISTENCY LOCAL_SERIAL;TRACING ON;INSERT INTO atlasmart_consistency.inventory_reservation_by_product(product_id,reservation_id,customer_id,state,created_at)VALUES ('sku-9','slot-1','customer-A','HELD',toTimestamp(now()))IF NOT EXISTS;TRACING OFF;
Wrong approach: “Use LWT for every update so everything is strongly consistent.”

LWT adds consensus rounds, coordination state, and tail-latency/failure sensitivity. It is appropriate for invariants such as uniqueness, compare-and-set, or guarded state transitions—not as a blanket replacement for ordinary mutations. Model most Cassandra data for idempotent, partition-local writes and reserve LWT for the small subset that truly needs linearizable conditional semantics.

4. What regular reads see after LWT

The cqlsh documentation distinguishes the serial phase from the normal learn phase. A successful conditional write with regular LOCAL_QUORUM means a subsequent read at an appropriate intersecting regular CL can observe the learned value. A serial read (SERIAL/LOCAL_SERIAL) is a separate, more expensive mechanism intended to read the current Paxos state consistently. Do not set SERIAL as a general-purpose default for ordinary SELECTs.

CQL · compare regular and serial read intent
CONSISTENCY LOCAL_QUORUM;SELECT * FROM atlasmart_consistency.inventory_reservation_by_productWHERE product_id='sku-9' AND reservation_id='slot-1';-- Serial reads are specialized; use only when the invariant needs them.CONSISTENCY LOCAL_SERIAL;SELECT * FROM atlasmart_consistency.inventory_reservation_by_productWHERE product_id='sku-9' AND reservation_id='slot-1';CONSISTENCY LOCAL_QUORUM;

Check your understanding

  1. What phase does LOCAL_SERIAL control for an IF statement?
  2. What does regular LOCAL_QUORUM control on a successful LWT?
  3. Why can two ordinary LOCAL_QUORUM writes both violate a uniqueness decision?
  4. What should two competing IF NOT EXISTS inserts show?
  5. Should SERIAL be the default SELECT consistency?
Review the answers

1. The Paxos/serial phase of the lightweight transaction.

2. The normal learn/data phase and ordinary request consistency, separate from the serial phase.

3. Quorum acknowledgment alone is not compare-and-set consensus; concurrent writers can both issue valid ordinary mutations.

4. Exactly one condition should apply; the loser receives applied=false with the current state.

5. No. Serial reads are specialized and more expensive; ordinary reads should use a regular CL derived from their invariant.

Production judgment

Choose consistency from a business invariant, topology, RF, and failure budget—not from a cluster-wide slogan. Record which reads must observe which writes, whether the invariant is local to one DC or global, whether conditional uniqueness/compare-and-set is required, and what latency/availability degradation is acceptable when replicas or a whole DC are unavailable. Then test that contract with the real driver, routing policy, request timeout, retry/speculative-execution policy, idempotency classification, and representative network latency.

Consistency level does not replace durable commit-log/storage design, repair, backup/restore, security isolation, schema/partition design, compaction/tombstone management, or application-level idempotency. ALL is not “permanent durability”; LOCAL_ONE is not tenant isolation; a timeout is not proof that a write failed; and a successful weak write does not promise a subsequent weak read will be fresh. Storage-Attached Indexing (SAI) or vector search can add read work but do not redefine RF/CL arithmetic. Managed Cassandra services may restrict topology visibility or CL choices; verify provider semantics rather than assuming Apache Cassandra behavior is exposed unchanged. Lesson 5 turns these mechanisms into an application consistency matrix and shows how to encode different regular/serial consistency per query in the Java driver.

Summary and next bridge

Regular CL and serial CL solve different problems. Ordinary mutations use replica acknowledgments; conditional LWT operations add Paxos and a serial consistency scope. Next, map those choices to concrete AtlasMart business invariants rather than one inherited default.

Authoritative references

Re-check these version-sensitive sources when regenerating this course.

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.