Batches are the most misused CQL feature: right for multi-table consistency, wrong for performance.
BEGIN BATCH ... APPLY BATCH; groups writes. Its purpose is atomicity, not speed.
A logged batch (the default) first writes the batch to a batchlog on other nodes. If the coordinator fails part way, the batchlog is replayed, so eventually all or none of the statements apply. This is how you keep denormalized tables (users_by_id and users_by_email) in sync. There is no isolation across partitions: a reader may briefly see one table updated and not the other, and there is no rollback.
A batch whose statements all target the same partition is applied as a single atomic and isolated mutation on each replica, with no batchlog needed. That's efficient and a good use of batches.
Unlogged batches skip the batchlog and provide no atomicity across partitions.
What batches are not: a way to bulk load. A multi-partition batch makes one coordinator do all the work and hold everything in memory, instead of spreading writes across the cluster. For many independent writes, send individual (asynchronous, token-aware) statements in parallel. Cassandra warns when a batch exceeds batch_size_warn_threshold (5 KiB by default) and rejects it above batch_size_fail_threshold (50 KiB).
Counter updates can only be batched with other counter updates (BEGIN COUNTER BATCH).
Example
-- keep two denormalized tables in sync: all-or-nothing (eventually)
BEGIN BATCH
INSERT INTO shop.users_by_email (email, user_id, name)
VALUES ('ana@example.com', 5b6962dd-3f90-4c93-8f61-eabfa4a803e2, 'Ana');
INSERT INTO shop.users (user_id, email)
VALUES (5b6962dd-3f90-4c93-8f61-eabfa4a803e2, 'ana@example.com');
APPLY BATCH;
-- single-partition batch: atomic and isolated, no batchlog needed
BEGIN UNLOGGED BATCH
INSERT INTO shop.order_items (order_id, sku, qty) VALUES (9a3e3b6e-0e4d-4c39-9a52-6a8f1f5c2b11, 'PEN', 3);
INSERT INTO shop.order_items (order_id, sku, qty) VALUES (9a3e3b6e-0e4d-4c39-9a52-6a8f1f5c2b11, 'PAD', 1);
APPLY BATCH;Remember
- Logged batches guarantee all statements eventually apply
- No isolation across partitions and no rollback
- Single-partition batches are atomic, isolated and cheap
- Don't use multi-partition batches for bulk loading
Watch out for
- Batching thousands of unrelated rows to 'speed up' inserts, overloading a single coordinator.