Problem
Strong consistency across services, regions, or replicas requires coordination that adds latency and reduces availability. Yet naive asynchronous replication leads to stale reads, lost updates, and confusing user experiences.
Design systems that tolerate temporary divergence between replicas and converge reliably without blocking on coordination.
Strong consistency across services, regions, or replicas requires coordination that adds latency and reduces availability. Yet naive asynchronous replication leads to stale reads, lost updates, and confusing user experiences.
Eventual consistency guarantees that, absent new updates, all replicas will eventually hold the same value. The engineering challenge is making the interval between now and eventually short, observable, and harmless.
A write is applied to its owning store and published as an event or captured by change data capture. Consumers update their replicas or read models asynchronously. Because delivery may be duplicated or reordered, handlers are idempotent and use version numbers or timestamps to ignore stale updates. When concurrent writes collide, a rule decides the winner or merges them, as with CRDTs. Periodic reconciliation compares sources of truth with replicas and repairs mismatches that events missed.
-- Version-guarded idempotent upsert
INSERT INTO customer_view (id, name, version)
VALUES (:id, :name, :version)
ON CONFLICT (id) DO UPDATE
SET name = EXCLUDED.name,
version = EXCLUDED.version
WHERE customer_view.version < EXCLUDED.version;
Teams adopt this approach when services own separate data stores and must stay loosely synchronized; multi-region deployments need local writes and low latency. It is a poor fit when operations require immediate global uniqueness or strict invariants, or when stale data would create safety, legal, or financial harm. The central tensions are freshness vs availability and latency; simple conflict rules vs data loss risk; client complexity vs user-visible correctness. The main benefits are that it delivers: higher availability and lower write latency; loose coupling between services; scales across regions and partitions; natural fit for event-driven architectures. The main costs to budget for are: users can observe stale or reordered data; conflict resolution adds complexity; debugging convergence problems is difficult; requires idempotent and commutative handling. Governance typically looks like this: each data domain documents its staleness tolerance and conflict rule. Expect adoption cost to be medium: eventing, reconciliation, and UX design, and a best fit for medium to large teams with distributed data ownership. Critics point out that eventual provides no bound on how long divergence lasts without extra engineering, and that application developers frequently underestimate conflict scenarios. Treat these concerns as design inputs, and revisit the decision as traffic, team size, and failure history change.