Consistency, Replication, Transactions, and Conflict Handling
Choosing a NoSQL data model does not automatically choose a consistency model. Document, key-value, wide-column, and graph describe how data is represented. Replication, transaction scope, and read/write guarantees are separate design choices.
data model
|
+-- document / key-value / wide-column / graph
distribution
|
+-- leader / multi-leader / leaderless / sharded
guarantees
|
+-- atomicity / isolation / session consistency / eventual consistency
A document database can support multi-document transactions. A key-value store can provide linearizable operations for selected keys. A relational database can use asynchronous replicas. Avoid treating SQL and NoSQL as shorthand for guarantees they do not necessarily imply.
Start with the business invariant
Write the rule before choosing the mechanism.
Examples:
- inventory must not become negative,
- a username must be unique,
- an order total must match its line items,
- a user should see their own recent profile update,
- recommendation results may be a few minutes stale.
The first three are correctness constraints. The last two are visibility and freshness requirements.
Atomic over what boundary?
Atomicity means all-or-nothing within a defined scope.
A store may guarantee:
one key update is atomic
without guaranteeing:
updates to 100 independent keys are atomic
A document database may make one-document changes atomic and offer an optional broader transaction API.
Always ask: atomic over which keys, documents, partitions, or shards?
Single-record atomicity
If one aggregate is stored together, atomic updates are simpler.
Example inventory document:
{
"sku": "DB-101",
"available": 7,
"reserved": 3
}
A conditional update can move units between fields without exposing a half-finished state. This is one reason aggregate boundaries matter in NoSQL modeling.
Cross-partition transactions
When a transaction spans partitions or shards, more coordination is required.
single partition
|
v
local coordination
many partitions
|
v
distributed coordination
|
v
more latency and failure cases
Use broad transactions when the business invariant requires them, not merely because the API exists.
Lost updates
Two clients read version 7.
Client A writes version 8.
Client B still holds version 7 and tries to write.
Without concurrency control, B may overwrite A.
Use optimistic concurrency:
update only if version = 7
If zero records match, another writer won and the stale operation must reload/retry.
Compare-and-set
Conditional writes are a common NoSQL primitive:
if current value == expected:
write new value
else:
fail
Useful for:
- versioned updates,
- claiming work,
- leases,
- uniqueness coordination.
Replication
Replication creates copies:
client
|
v
replica/leader A
|------> replica B
`------> replica C
Replication can improve availability and read capacity, but introduces questions about acknowledgement, lag, failover, and conflict handling.
Synchronous replication
A write waits for enough replicas before success.
Advantages:
- stronger durability under defined failures,
- fresher failover state.
Trade-offs:
- higher write latency,
- reduced availability if enough replicas cannot respond.
Asynchronous replication
The primary may acknowledge before replicas apply the write.
client -> primary -> success
|
`---- later ----> replica
Advantages:
- lower write latency.
Trade-offs:
- replicas can be stale,
- recent acknowledged data can be at risk under some failover designs.
Read-after-write
A user updates a profile and immediately reloads it.
If the read goes to a lagging replica, the old value can reappear.
Possible strategies:
- read from the writer/leader after a write,
- use session consistency,
- sticky routing,
- wait for a replica to catch up,
- choose a stronger read consistency setting.
Eventual consistency
Eventual consistency means replicas are expected to converge if updates stop and communication recovers.
It does not define:
- how long convergence takes,
- what a client sees during lag,
- how concurrent conflicts are resolved,
- whether acknowledged writes can be lost.
State a concrete staleness budget instead of saying only "eventual is fine."
Example:
recommendations may lag by 5 minutes
inventory reservations may not be stale
Leader-based replication
writers
|
v
leader
|----> follower
`----> follower
This gives a clear write-ordering point but requires leader failover and can make follower reads stale.
Multi-leader replication
Several sites accept writes.
EU leader <---- replication/conflicts ----> US leader
This may reduce local write latency but concurrent writes can conflict.
Leaderless and quorum-style replication
A coordinator may write/read several replicas.
With three replicas, a quorum is two.
The intuition is that overlapping read and write sets can improve freshness, but exact guarantees depend on the product, topology, failure modes, and conflict-resolution rules.
Cassandra is a concrete example with tunable consistency levels.
CAP theorem
CAP concerns behavior during a network partition. A distributed system cannot provide both complete availability and linearizable consistency across separated sides of the partition.
"Pick two of three" is an oversimplification because real distributed deployments cannot simply opt out of partitions.
Use CAP to reason about partition-time behavior, not as a product scorecard.
Conflict handling
Suppose two regions concurrently update the same profile:
EU: display_name = "Alice Smith"
US: display_name = "A. Smith"
After reconnection, the system needs a rule.
Possible strategies:
- last-write-wins,
- explicit conflicting versions,
- application merge,
- CRDT-specific merge,
- single-writer ownership.
Last-write-wins
LWW is simple but can silently discard valid concurrent work.
If two users update different fields of the same object and the whole object is resolved by one timestamp, one change can vanish.
Use it only when that loss policy matches business semantics.
Application merge
Some data can be merged naturally.
Two offline shopping-list edits:
region A adds milk
region B adds bread
can become:
milk + bread
A bank balance cannot safely use an arbitrary merge rule.
Conflict resolution is data-type specific.
CRDT idea
Conflict-free Replicated Data Types define mergeable state/operations for specific semantics, such as counters or sets.
They are powerful but not a universal answer. Arbitrary business objects do not become safely mergeable just by calling them CRDTs.
Clock problems
Physical clocks can drift or jump. A later wall-clock timestamp is not always a causally later operation.
Distributed systems may use logical clocks, vector clocks, hybrid logical clocks, or engine-specific version metadata.
Transactions across services
Checkout may involve:
reserve inventory
charge payment
create order
publish event
One database transaction usually cannot roll back an external payment or message broker.
Use workflow patterns such as sagas and compensating actions when work spans systems.
Outbox pattern
A transaction can write both:
business state
+
outbox event
Then a separate publisher reliably forwards the outbox event.
This avoids the gap where the database commits but event publication fails.
Idempotency
Retries are normal because clients may not know whether a timed-out request committed.
Use stable request IDs:
idempotency_key = checkout-6f...
A repeated request can return the previous result instead of creating a duplicate order.
Timeout ambiguity
A client timeout means:
response was not observed
not necessarily:
server rolled back
The server may have committed.
This is why idempotency and post-timeout verification matter.
At-least-once delivery
Message systems frequently deliver an event more than once.
Consumers should handle duplicates:
event ID
|
v
already processed?
|-- yes -> return prior result
`-- no -> process and record
End-to-end "exactly once" cannot be inferred from a single component label.
Retry the whole logical operation
On a serialization/concurrency conflict:
read
validate
compute
conditional write
|
conflict?
|-- yes -> reload and retry
`-- no -> success
Retry the whole operation because earlier reads may no longer be valid.
Bound retries and use backoff.
Multi-region latency
Strong synchronous coordination across distant regions costs network time.
EU request ---- round trip ----> US replica
Place data and write leadership near the workload when possible, while meeting durability and residency requirements.
"Globally distributed" does not make geography free.
Choose guarantees per operation
A single system can need several levels:
| Operation | Requirement |
|---|---|
| product recommendations | minutes of staleness may be acceptable |
| profile read after update | read-your-writes/session consistency |
| inventory reservation | conditional or transactional correctness |
| unique username claim | compare-and-set or transaction |
| analytics projection | eventual consistency |
Do not use the strongest option everywhere without need. Do not weaken correctness-critical operations merely for benchmark speed.
Failure testing
Test the hard cases:
- replica unavailable,
- leader failover,
- network delay,
- duplicate request,
- timeout after commit,
- stale replica read,
- concurrent writers.
Guarantees matter most during failures.
Design checklist
For each operation:
- What invariant must hold?
- What is the atomicity boundary?
- Can concurrent writers conflict?
- How stale may reads be?
- Must the writer read its own write?
- What happens during a partition?
- What acknowledgement is required?
- How are conflicts resolved?
- Can retries be made idempotent?
- What happens after timeout ambiguity?
- Does the workflow cross services?
- Has failure behavior been tested?
Common mistakes
"NoSQL means eventual consistency"
False as a category statement.
"Transactions make modeling irrelevant"
Distributed transaction cost still matters.
"Replica means backup"
Replication can copy bad changes.
"Timeout means failure"
The operation may have committed.
"Last write wins is harmless"
Valid concurrent work can disappear.
Strongest consistency everywhere
May add latency with no product benefit.
Weak consistency for money/inventory invariants
Can violate correctness.