Uniqueness and check-then-act operations (usernames, inventory) need more than last-write-wins.
Plain writes are blind upserts. When you need to check before writing, Cassandra offers lightweight transactions (LWT): conditional writes using a Paxos consensus round among the replicas, which makes them linearizable for that partition.
INSERT ... IF NOT EXISTSclaims a key only if it's free, e.g. a unique username,UPDATE ... SET qty = 4 WHERE ... IF qty = 5changes a value only if it still has the expected one,DELETE ... IF EXISTSandUPDATE ... IF EXISTSact only on existing rows.
The result contains an [applied] column; when false, it also returns the current values so you can decide what to do.
The Paxos phase uses the serial consistency level: SERIAL (across data centers) or LOCAL_SERIAL; the commit uses the normal consistency level. Read with SERIAL if you must see the result of in-progress LWTs.
Costs and limits:
- several round trips, so roughly 4x the latency of a normal write, and contention on the same partition causes timeouts,
- conditions are limited to one partition; there are no multi-partition transactions (general ACID transactions via the Accord protocol are planned for a later major version),
- mixing LWT and non-LWT writes on the same data breaks the guarantees.
Use LWTs for the rare operations that truly need them, not for every write.
Example
-- unique username claim
INSERT INTO shop.usernames (username, user_id)
VALUES ('ana', 5b6962dd-3f90-4c93-8f61-eabfa4a803e2) IF NOT EXISTS;
-- [applied]
-- True
INSERT INTO shop.usernames (username, user_id)
VALUES ('ana', 0d1d8cd6-31ab-4a4b-a6d3-6c0e2b1b9a10) IF NOT EXISTS;
-- [applied] | username | user_id
-- False | ana | 5b6962dd-3f90-4c93-8f61-eabfa4a803e2
-- optimistic stock decrement
SERIAL CONSISTENCY LOCAL_SERIAL;
UPDATE shop.stock SET qty = 4 WHERE sku = 'PEN' IF qty = 5;
-- [applied] | qty
-- False | 3 -> re-read and retry with the current valueRemember
- IF NOT EXISTS / IF col = value give compare-and-set via Paxos
- Check the [applied] column; failures return current values
- Serial CL governs the Paxos phase (SERIAL or LOCAL_SERIAL)
- Single-partition only and several times slower than plain writes
Watch out for
- Mixing conditional and unconditional writes to the same column, which can silently break linearizability.