Definition
- Strong consistency : every read returns the most recent committed write; all observers see a single, up-to-date value.
- Eventual consistency : in the absence of new writes, all replicas converge to the same value after some delay; reads may temporarily return stale data.
- Read-your-writes : a user always sees their own changes immediately, even if other users see them slightly later.
- Causal consistency : preserves cause-and-effect ordering between related operations.
- Tunable consistency : choosing per operation how many replicas must acknowledge (e.g., Cassandra's quorum).
When Rajesh transfers money at National Bank of India, the moment the transfer succeeds, every teller and screen must show the new balance : no exceptions, because a wrong balance could allow a double-spend. That is strong consistency. But when Rajesh likes a post on the bank's community feed, it is fine if his friend sees the updated like count a second later. That is eventual consistency.
Understanding the Concepts
What is strong consistency?
Strong consistency means that once a write commits, any subsequent read anywhere returns that value or newer. Achieving it requires coordination such as a single leader, quorum reads and writes, or synchronous replication, all of which add latency.
package com.bank.consistency;
import java.math.BigDecimal;
public class StrongConsistencyRead {
public BigDecimal balanceStrong(String accountId) {
return leader.read(accountId); // always the latest committed value
}
}
What is eventual consistency?
Eventual consistency relaxes the guarantee. A write is propagated asynchronously to replicas, so for a short window different replicas may hold different values, but they all converge. This allows low-latency, highly available reads from any replica.
package com.bank.consistency;
public class EventualConsistencyRead {
public long likeCountEventual(String postId) {
return nearestReplica.read(postId); // may lag; converges shortly
}
}
What is read-your-writes consistency?
Read-your-writes guarantees a user sees their own writes immediately even if others see them slightly later. I implement this by routing a user's own reads to the leader right after they write.
package com.bank.consistency;
public class ReadYourWrites {
public String read(String query, boolean justWrote) {
return justWrote ? leader.query(query) : anyReplica.query(query);
}
}
What is tunable consistency?
Tunable consistency, offered by databases like Cassandra, lets you choose per operation how many replicas must acknowledge. Write to a quorum and read from a quorum, and you get strong consistency. Write to one and read from one, and you get eventual consistency with lower latency.
package com.bank.consistency;
public class TunableConsistency {
// Quorum: W + R > N guarantees strong consistency
// N=3, W=2, R=2 -> strong (2+2 > 3)
// N=3, W=1, R=1 -> eventual (1+1 < 3)
public String consistencyLevel(String dataType) {
return switch (dataType) {
case "balance" -> "QUORUM (strong)";
case "like_count" -> "ONE (eventual, fast)";
default -> "QUORUM (safe default)";
};
}
}
How does the domain decide the choice?
| Data type | Consistency | Reason |
|---|---|---|
| Account balance | Strong | Wrong value = double-spend |
| Transaction ledger | Strong | Append-only, audit-critical |
| Social feed likes | Eventual | Brief staleness harmless |
| Analytics counters | Eventual | Approximate is fine |
| Dashboard metrics | Eventual | Seconds of lag acceptable |
What is the cost of strong consistency?
Strong consistency requires coordination, which adds latency and can reduce availability during partitions (CAP theorem). I apply it only where a wrong or stale value causes real harm.
What are the middle grounds?
Between strong and eventual are read-your-writes (user sees own changes), causal consistency (preserves cause-effect), and session consistency (monotonic reads within a session).
What should a senior engineer know?
Consistency is a per-data-type decision, not a single global setting. The same bank uses strong consistency for the ledger and eventual for the community feed. Deliberately spending strong consistency only where needed and relaxing everywhere else gains speed, scale, and availability.
Visual Overview
Consistency Spectrum ◄── EVENTUAL ─────────────────────── STRONG ──► ONE replica Read-your-writes Quorum Leader-only (fast, stale) (own changes) (majority) (always fresh) ┌──────────┐ ┌──────────────┐ ┌──────────┐ ┌──────────┐ │ Feeds │ │ User profile │ │ Payments │ │ Ledger │ │ Counters │ │ display │ │ Balance │ │ Transfers│ │ Analytics│ │ after edit │ │ reads │ │ Audit │ └──────────┘ └──────────────┘ └──────────┘ └──────────┘ Tunable consistency (Cassandra): W=1, R=1 -> eventual (fast) W=2, R=2 -> strong (N=3, W+R > N) W=3, R=1 -> strong writes, fast reads Per-data-type decision: Bank balance -> STRONG (wrong value = double-spend) Like count -> EVENTUAL (stale by 1 second is fine) User profile -> READ-YOUR-WRITES (see own changes)
Key Takeaway
Strong consistency guarantees every read returns the most recent committed write, while eventual consistency guarantees only that replicas converge after a delay. The skill is matching the level to the data.
For banking, I insist on strong consistency for balances and the ledger. A stale balance could let money be spent twice. I pay the latency and coordination cost because correctness of money is non-negotiable.
Eventual consistency is right where staleness is harmless. A like count or dashboard metric can lag by a second with no harm. I let any replica serve the read for low latency.
The refinement is middle grounds: read-your-writes ensures a customer sees their own change immediately, tunable consistency lets me choose per operation. Consistency is a per-data-type decision, not a global setting. I spend strong consistency where correctness is sacred and relax everywhere else.
Remember one sentence: use strong consistency for money where staleness causes real harm, eventual consistency for everything else, and apply the decision per data type, not globally.
---