"Coherence is not about eliminating all inconsistency—it's about understanding where consistency matters and designing boundaries that make reasoning possible."
Distributed systems face a fundamental tension: autonomy versus consistency. Services need independence to scale and evolve, yet they must coordinate to deliver coherent user experiences.
We design for eventual coherence—systems that converge toward consistent states through well-defined boundaries, contracts, and coordination patterns. Perfect consistency is neither possible nor necessary at scale.
Define clear boundaries where models, terminology, and rules apply. Each bounded context owns its domain and exposes explicit contracts.
A "Customer" in the Billing context has different attributes and behaviors than a "Customer" in the Support context. Each context maintains its own model, and integration happens through explicit mapping at boundaries.
Choose appropriate consistency guarantees for each use case: strong consistency for transactions, eventual consistency for replication.
Immediate consistency. Use for critical transactions (payments, inventory).
Delayed consistency. Use for high-availability reads (social feeds, search indices).
Cause-effect ordering. Use for collaborative systems (chat, document editing).
Synchronize state across services through domain events. Each service reacts to events and updates its local state independently.
Use distributed locking for critical sections where strong coordination is required. Employ leader election for singleton processes.
Cluster related entities into aggregates with a single root. Enforce consistency boundaries within the aggregate, eventual consistency between aggregates.
Translate between contexts to prevent external models from polluting your domain. Map concepts at boundaries to maintain context purity.
For tightly coupled contexts, share a small core model. Coordinate changes carefully—shared kernel is high-friction but low-translation overhead.
Document relationships between contexts: customer-supplier, conformist, partnership. Make integration patterns explicit.
Monitor consistency drift across services. Track event propagation delays, reconciliation errors, and out-of-sync states.
Design for failure recovery. Implement idempotent operations, retry with backoff, and reconciliation jobs for drift correction.