Architecture Realities: Why Distributed Systems Prefer "Good Enough" Over Perfect
Introduction:
Perfectionism is a virtue in many engineering contexts. Well-tested code, carefully reviewed designs, and thoroughly validated assumptions produce better systems. But distributed systems operate under constraints that make perfectionism not just impractical but actively counterproductive.
In a distributed system, achieving perfect consistency, perfect accuracy, or perfect coordination requires trade-offs that degrade availability, increase latency, and reduce resilience in ways that users experience directly. The systems that work best in production are not the ones that achieve perfect outcomes — they are the ones that define what "good enough" means for their specific domain and engineer toward that threshold deliberately.
Understanding why distributed systems prefer good enough over perfect is not an excuse for low standards. It is a recognition that in the presence of network partitions, hardware failures, and concurrent access, perfection is not a stable equilibrium.
Perfect Consistency Requires Coordination That Costs Too Much:
Strong consistency in a distributed system means that every node sees the same data at the same time and that every read reflects the most recent write. Achieving this requires coordination — before a write is acknowledged, it must be confirmed by multiple nodes, and reads must verify they are seeing the latest version.
This coordination introduces latency on every operation. In a system where nodes are geographically distributed, the coordination latency compounds with network round-trip times to produce response times that are unacceptable for interactive applications. During network partitions — which are not hypothetical in production but a routine operational reality — coordination becomes impossible and the system must choose between remaining available with potentially stale data or becoming unavailable until the partition resolves.
Most user-facing systems cannot afford unavailability. They accept that some reads may return slightly stale data in exchange for remaining operational when the network misbehaves.
Eventual Consistency Is Good Enough for Most Use Cases:
Eventual consistency guarantees that if no new writes occur, all replicas will converge to the same value given sufficient time. The convergence window is typically milliseconds to seconds in well-designed systems — short enough that most users never notice the inconsistency.
For the vast majority of use cases, this is genuinely good enough. A social media feed that shows a post two seconds late is not broken. A product catalogue that reflects a price update with a brief delay does not cause meaningful user harm. A notification that arrives slightly out of order is an inconvenience, not a correctness failure.
The engineering challenge is identifying the specific cases where eventual consistency is not acceptable — financial transactions, inventory reservations, authentication state — and applying stronger guarantees selectively rather than universally. Applying strong consistency everywhere to handle the cases where it is necessary is the mistake that makes systems unnecessarily slow and fragile.
Approximate Answers Arrive Faster Than Exact Ones:
In distributed systems that process large volumes of data, computing exact answers often requires scanning every record, coordinating across every node, and waiting for every response before returning a result. This is expensive, slow, and sensitive to stragglers — nodes that respond slowly and hold up the entire computation.
Approximate algorithms — HyperLogLog for cardinality estimation, Count-Min Sketch for frequency counting, probabilistic data structures for membership testing — trade a small, bounded error for dramatically better performance. A HyperLogLog estimate of unique visitors that is accurate to within two percent arrives in milliseconds. An exact count may require seconds or minutes depending on data volume.
For the dashboards, analytics systems, and monitoring tools where these algorithms are typically used, two percent error is good enough. The decision being made from the data does not change based on whether unique visitors were 4,921,847 or 4,923,103. Speed and availability matter more than precision.
Idempotency Accepts Duplication Rather Than Preventing It:
In distributed systems, guaranteeing that an operation happens exactly once is extraordinarily difficult. Network failures cause retries. Retries cause duplicate operations. Preventing duplicates with certainty requires distributed coordination that reintroduces the consistency problems discussed above.
The practical alternative is idempotency — designing operations so that executing them multiple times produces the same result as executing them once. A payment that is submitted twice with the same idempotency key charges the customer once. A message that is delivered twice and processed twice produces the same state as if it were delivered once.
Idempotency accepts that duplication will occur and handles it gracefully rather than attempting to prevent it entirely. This is good enough — the outcome is correct even if the path to that outcome involved redundant operations.
Timeouts and Retries Accept Partial Failure:
A distributed system that waits indefinitely for a response from a downstream service will eventually exhaust its own resources — threads, connections, memory — as requests pile up waiting for responses that may never arrive. Perfect availability of every dependency is not achievable, so the system must decide how to behave when dependencies are slow or unavailable.
Timeouts accept that some requests will fail rather than waiting forever. Retries accept that the first attempt may fail and that trying again is better than giving up. Circuit breakers accept that a failing dependency should be bypassed temporarily rather than continuously retried.
None of these mechanisms produce perfect outcomes. Timeouts cause some requests to fail that would have eventually succeeded. Retries can cause duplicate operations. Circuit breakers cause requests to fail fast rather than succeed slowly. But these imperfect outcomes are better than the alternative — a system that becomes completely unavailable because one dependency is slow.
Good Enough Must Be Defined Explicitly:
The danger of accepting good enough is accepting it without defining what good enough means. Eventual consistency is good enough for social feeds but not for bank balances. Approximate counts are good enough for analytics dashboards but not for billing systems. At-least-once delivery is good enough for notification systems but not for financial transactions.
These boundaries need to be defined explicitly, documented, and enforced through system design. Good enough that is never defined becomes a rationalisation for any level of quality — and that is where distributed systems accumulate correctness bugs that are expensive to find and difficult to fix.
Conclusion:
Distributed systems prefer good enough over perfect not because their engineers lack ambition but because the cost of perfection in the presence of network failures, concurrent access, and geographic distribution is higher than most systems can afford to pay.
The engineers who build the most reliable distributed systems are not the ones who insist on perfect consistency everywhere. They are the ones who understand precisely where perfection is necessary, accept good enough everywhere else, and define the boundary between the two with enough clarity that the entire team can build toward the same standard.
Enjoyed this post?
Stay in the loop
New posts + weekly digest, straight to your inbox.
Create a free account
- Save posts to your vault
- Like posts & build history
- New-post alerts
No comments yet. Be the first to comment!