Consistency patterns
By Oleksandr Andrushchenko, Published on
Consistency patterns describe how systems behave when multiple actors read and write shared data, especially under concurrency, failure, or distribution. Database transactions are one of the strongest tools for enforcing consistency, but they coexist with weaker models that trade correctness guarantees for availability and scale. A messaging app displaying unread counts slightly out of date but never losing messages illustrates how different consistency levels coexist in one system.
Modern system design rarely relies on a single consistency model across all components. Strong consistency is typically reserved for critical invariants, while weaker models are applied to performance-sensitive paths. A checkout service enforcing strict payment rules alongside an eventually consistent recommendation engine is a realistic production setup.
Strong Consistency and Transactions
Strong consistency guarantees that once a write is acknowledged, all subsequent reads return the latest value. Database transactions operating at serializable or repeatable read isolation levels are the most common implementation. A banking system updating an account balance must ensure that every read immediately reflects the most recent debit or credit.
Strong consistency simplifies reasoning but increases coordination costs. Locks, synchronous replication, or quorum reads introduce latency and reduce throughput. A globally distributed user profile database often avoids strong consistency because cross-region coordination slows down simple reads.
- Use strong consistency for monetary balances, quotas, and identity data.
- Keep strongly consistent transactions short-lived.
- Limit the scope to a single database or shard.
Weak Consistency in High-Throughput Systems
Weak consistency allows reads to return stale or out-of-order data without guarantees on when updates become visible. Systems prioritize availability and latency over correctness. A metrics dashboard showing request counts that lag a few seconds behind real traffic is a typical weakly consistent workload.
Weak consistency is often implemented via asynchronous replication, caching layers, or fire-and-forget writes. This model works well when correctness is statistical rather than absolute. A recommendation engine ranking content based on approximate engagement signals benefits more from throughput than exact counts.
- Apply weak consistency to analytics, logs, and telemetry.
- Ensure downstream consumers tolerate stale data.
- Document freshness expectations explicitly.
Eventual Consistency as a Design Pattern
Eventual consistency guarantees that, given no new updates, all replicas will converge to the same state over time. Unlike weak consistency, convergence is an explicit promise. A DNS system propagating record changes globally over several minutes demonstrates eventual consistency at Internet scale.
Eventual consistency is common in distributed databases, caches, and event-driven architectures. It enables horizontal scaling and fault tolerance but requires conflict handling. A shopping cart stored in a distributed key-value store may temporarily diverge between regions but eventually reflects the same items.
| Consistency Model | Guarantee | Latency | Typical Use Case |
|---|---|---|---|
| Strong | Immediate correctness | High | Payments, identity |
| Eventual | Convergence over time | Medium | Caches, carts |
| Weak | No ordering guarantees | Low | Metrics, analytics |
Transactions Inside Eventually Consistent Systems
Even in eventually consistent architectures, transactions remain valuable at local boundaries. Each service can enforce strong consistency internally while communicating asynchronously. An order service committing an order record transactionally before emitting an event is a common hybrid approach.
This pattern isolates failure domains and simplifies recovery. External systems react to committed facts rather than partial state. A billing service consuming order-created events avoids distributed transactions while maintaining internal correctness.
def create_order(conn, order_id, payload, outbox):
"""
Creates an order using a local database transaction
and records an event using the outbox pattern.
"""
with conn:
conn.execute(
"INSERT INTO orders (id, status) VALUES (?, ?)",
(
order_id,
"CREATED",
),
)
conn.execute(
"INSERT INTO outbox (event_type, payload) VALUES (?, ?)",
(
"OrderCreated",
payload,
),
)
# Publishing is done after commit
# to avoid distributed transactions
outbox.publish()
Consistency Trade-offs in Distributed Transactions
Distributed transactions attempt to extend strong consistency across services but increase coupling and operational risk. Blocking protocols amplify failures. A stalled coordinator preventing inventory release during a partial outage is a classic failure mode.
Eventual consistency with compensations is usually preferred. Business workflows are modeled as state machines rather than atomic operations. A refund process reversing a failed shipment instead of rolling back the original order reflects this approach.
- Avoid strong consistency across network boundaries.
- Use compensating actions for irreversible operations.
- Design workflows to tolerate partial progress.
Choosing the Right Consistency Level per Use Case
No single consistency model fits all workloads. The correct choice depends on business impact, failure tolerance, and scale requirements. A leaderboard accepting slightly stale scores improves performance without affecting fairness.
Explicitly mapping operations to consistency levels prevents accidental over-engineering. Strong consistency should protect invariants, eventual consistency should support workflows, and weak consistency should optimize observability and insights. A design document classifying data paths by consistency requirements reduces ambiguity during implementation.
Effective system design treats consistency as a spectrum rather than a binary choice. Database transactions, weak reads, and eventual convergence all coexist when applied deliberately and measured continuously.