A Cassandra-based marketplace stores an order's status in orders_by_id, its status in orders_by_customer, and an operational view in open_orders_by_region. The application uses a logged batch to update the three tables and assumes every reader sees all three changes at once. During a network fault, one query shows SHIPPED while another still shows PAID. Is the batch broken, and what guarantee should the application design around?
Assume the three rows can belong to different Cassandra partitions. The ordinary order lookup must remain correct enough to drive fulfillment. The customer list and regional operations view may lag under a defined contract, but cannot silently authorize shipment of an unpaid order.
Think first
A Cassandra application writes order state, a customer timeline and an audit summary in three partitions. Legal wants every audit reader to see the same transition set. Explain the gap in the logged-batch approach and redesign the audit read contract.
Take a few minutes to form an approach, then compare it with the worked explanation.
Reveal the worked explanation
Atomic completion is not simultaneous visibility
A logged multi-partition batch is designed to make the batch's mutations eventually get applied as a unit of intended work despite coordinator failure, under the storage system's recovery assumptions. It is not a general-purpose isolated transaction in which other clients can only see an all-old or all-new snapshot across partitions.
Cassandra's documented batch semantics distinguish single-partition isolation from multi-partition batch behavior. The documentation explicitly states that other clients may read early mutations while the rest of a multi-partition batch is still being applied. Cassandra BATCH
A logged Cassandra batch tracks multiple mutations for eventual completion, but readers can observe intermediate cross-partition visibility.
That is the root of the scenario. A successful mechanism for not forgetting remaining writes is not automatically a mechanism for presenting an atomic read snapshot across those writes.
Walk through a coordinator failure
Suppose the application submits three mutations:
A orders_by_id o481 -> SHIPPED
B orders_by_customer o481 -> SHIPPED
C open_orders_by_region remove o481
The coordinator records the batch obligation in the batchlog as appropriate. It sends work toward the relevant replicas. Mutation A becomes visible to a read, while mutation B has not yet become visible under the reader's consistency and timing. The coordinator fails before every target has completed.
A logged batch provides information needed to continue applying unfinished mutations, assuming its recovery and replicas remain available. But a reader checking A and B during the interval can observe different representations.
A request timeout introduces further uncertainty. It does not prove the batch failed or that none of its effects happened. The client should investigate a stable order version or retry safely according to the write contract, not issue a new unrelated order transition.
Make one order fact authoritative
For this scenario I would identify the one record that owns the order's business state. orders_by_id could serve that role if its update path enforces allowed transitions and the required concurrency behavior.
orders_by_customer and open_orders_by_region would then be derived views, deliberately allowed to lag within a visible freshness contract. If a shipping worker needs to decide whether shipment is authorized, it consults the authoritative business state and any payment evidence required by the invariant. It cannot rely on the potentially stale regional list alone.
The key is not a table name. It is an explicit ownership rule: which service and record decide whether an order has moved from PAID to SHIPPED, and under what conditional or coordinated write protocol?
QUORUM acknowledgments do not make arbitrary cross-partition rows one isolated transaction. A conditional transition needs a separate supported coordination protocol.
What if business really needs all three views to agree?
First challenge the requirement. A shipping worker may need one strong decision, while a dashboard can tolerate temporary lag. Requiring three denormalized query tables to become visible simultaneously may be an unnecessary cost that fights the database model.
If a consumer must read a coherent set, one approach writes a shared version or generation marker and makes the reader pin a committed generation after the required records exist. That protocol needs immutable, version-addressed records, a safely read committed marker, retention, and reads that establish every required version is available. Seeing the marker at one replica does not prove another replica can return all referenced rows; missing or older versions must make the read wait, retry or fail rather than return a partial generation. That is a protocol the application must carefully implement and validate. It is not supplied merely by wrapping writes in BEGIN BATCH.
Another approach routes the coherence-critical query through one authoritative record and treats the other tables as materialized projections. That sacrifices some lookup convenience but simplifies correctness.
A full transactional datastore supporting the required multi-record snapshot semantics is also an option when the workload fundamentally demands them. It would be a reasonable architectural tradeoff, not an admission that every Cassandra model is unsuitable.
Logged batches have a real cost
A tempting performance idea is to place 10,000 unrelated writes in one giant batch to reduce client calls. That is often a poor Cassandra design. Cross-partition logged batches add coordinator and batchlog work, and they do not turn unrelated partition writes into one high-throughput sequential operation.
DataStax's guidance specifically warns that multi-partition batches can worsen latency and throughput and recommends them for limited cases where atomic application is the requirement, not as a bulk-loading optimization. Batching inserts and updates
For bulk ingestion, independent asynchronous writes with bounded concurrency and appropriate routing may be more efficient, as long as the business semantics permit independent success and recovery.
How should the system detect and repair drift?
The architecture needs a way to compare projections with the authoritative order state. A background reconciliation job can scan recent transitions and detect missing or outdated customer and regional views. It should repair by stable order identity and version, rejecting an older repair that would overwrite a newer state.
Monitor unresolved projection lag, consistency of representative samples, failed mutation categories and batchlog pressure. A successful batch response alone cannot demonstrate that every query representation was observed simultaneously.
If three screens may disagree for a few seconds, document the lag and repair it. If a cross-table contradiction would authorize an irreversible side effect, move that decision to one enforced authority or a database protocol that actually supplies the required snapshot and conditional semantics. Do not stretch the meaning of “atomic” until it conceals the difference.
Go deeper
Optional depth: no rollback illusion
A Cassandra logged batch is not a relational transaction in which the application can roll back already visible mutations to restore a snapshot. Its batchlog supports completing the intended writes under its contract. The outcomes depend on the failure and consistency settings. Cassandra documents single-partition isolation separately from the cross-partition batch guarantee. Apache Cassandra CQL DML
Check your reasoning
Give a specific partial-visible multi-partition execution.
Separate eventual atomic batch application from isolated read snapshots.
Designate an authoritative order state.
Explain projection versioning, reconciliation and conditional decisions.
Reject giant logged batches as a universal loading optimization.
Common mistake: A logged Cassandra batch ensures every reader sees either all old or all new cross-partition rows.
Read the answer explanation
Treat the logged batch as a recovery mechanism and keep critical decisions at one authority — Logged batch completion does not give multi-partition read isolation. Readers need an explicit contract about sources of truth.
Apply it elsewhere
A service writes a user's notification preference into three denormalized tables. One table remains stale for 30 seconds. Which reads need a fresh authoritative check?
Compare your approach
Distinguish atomic application from multi-partition isolation. Show a partial-visible execution. Name an authoritative record. Protect irreversible decisions. Compare versioned projections, reconciliation and another datastore if truly necessary. Explain batchlog overhead.
One more constraint
Does a logged multi-partition batch guarantee a concurrent reader cannot see the first mutation until all other mutations are visible?
Quick revision
Cassandra's logged multi-partition batches help ensure intended mutations are applied despite partial failure, but they do not give isolated all-old or all-new reads across partitions. Treat one record as authoritative for business invariants, and make other query tables explicit projections with versioning and repair. If all-or-nothing cross-table visibility is essential, design an actual read protocol or use a datastore that provides the necessary transaction semantics. A large logged batch is not a general-purpose performance optimization.