Why Distributed Systems Fail When They Stop Thinking Like Queries
Hatched by Kai Nguyen
May 27, 2026
11 min read
3 views
84%
The hidden similarity between broken transactions and slow queries
What do a distributed checkout flow and a painfully slow SQL query have in common? More than most engineers realize. Both fail for the same deep reason: they try to do too much work in the wrong place, at the wrong time, with the wrong expectations about certainty.
In one case, a system assumes it can preserve perfect consistency across many services as if they were one database. In the other, a query assumes the database can still move quickly after you wrap indexed columns in functions, negate predicates, or force it to sort and group too much data. The result is the same kind of disappointment: the system still works, but it has become expensive, fragile, and unpredictable.
The real lesson is not just about sagas or SQL tuning. It is about a broader design principle: good systems reduce global coordination by making local work cheap, visible, and reversible. When that principle is violated, performance collapses, not always immediately, but inevitably.
The fastest system is not the one that does everything in one place. It is the one that lets each part do the smallest useful amount of work, then moves on.
Why consistency and performance are secretly the same problem
Traditional databases taught us to think in terms of atomicity: either the transaction succeeds, or it does not. That model is elegant because it hides complexity. But once a business process spans multiple services, each with its own database, that elegance breaks. You no longer have one tidy unit of work. You have a chain of local decisions, each with its own failure mode.
SQL optimization reveals the same pattern from another angle. A database query is fast when the engine can narrow the search space early, use indexes effectively, and avoid unnecessary work. When you add arithmetic to indexed columns, apply leading wildcards, or defer filtering until after expensive operations, you force the engine into broad scans and late decisions. The query still produces an answer, but it gets there by brute force.
That is the shared tension: coordination versus locality. In distributed systems, coordination means talking across services to preserve business correctness. In SQL, coordination means making the engine examine too much data before it can decide what matters. Both are expensive because they expand the area of uncertainty.
A useful mental model is to think of every system as paying three taxes:
- The tax of search: how much must be examined before the useful subset is known.
- The tax of coordination: how many components must agree before progress can continue.
- The tax of recovery: how hard it is to undo a bad step when something fails.
The Saga pattern is a way to lower the tax of coordination by replacing one global transaction with a sequence of local transactions plus compensation. Query tuning is a way to lower the tax of search by letting the engine use indexes, filter early, and avoid work it does not need. Different tools, same philosophy.
The Saga pattern is really a design for admitting imperfection
The most interesting thing about sagas is not that they preserve business workflows across services. It is that they accept an uncomfortable truth: in a distributed system, you often cannot know everything at once, and you often cannot roll everything back as if nothing happened.
That sounds like a compromise, but it is actually a strength. The saga pattern is built on local transactions, compensating transactions, and communication through events or messages. Taken together, these form a practical discipline for working with partial knowledge. Each service commits to a small truth it can enforce itself, then emits a signal so the next step can continue.
This resembles a well-tuned query plan more than it first appears. A query optimizer does not try to inspect the whole dataset in the most expensive way. It exploits structure. It says: if the data is indexed, start there. If the filter is selective, apply it early. If the result set should be small, stop once you have enough. In both cases, the system does not seek certainty through brute force. It seeks certainty through ordering.
That ordering matters. In a saga, the order of local transactions is not just workflow logic. It is a risk management strategy. If credit reservation must happen before inventory decrement, or payment authorization before shipment, that sequencing reflects which uncertainties should be resolved first. Similarly, in SQL, pushing a selective WHERE clause early is not a cosmetic optimization. It is a way of shrinking ambiguity before the expensive parts of the plan begin.
Consider a simple e commerce example. A user places an order involving payment, inventory, and shipping. A monolithic ACID transaction would try to make all of these one indivisible act. In a microservices architecture, that becomes brittle because payment, stock, and logistics may live in different systems. A saga instead allows payment authorization to happen locally, then inventory reservation, then shipping initiation. If shipping fails, a compensating action may release inventory or void the authorization.
Now compare that with a query that needs only recent orders above a threshold. If the database can use an index on order date and apply the threshold immediately, it can avoid scanning old rows. If instead the query wraps the date column in a function, or adds a leading wildcard search, the engine loses the shortcut and has to do more work. The difference is not just speed. It is whether the system is allowed to trust structure.
Efficient systems are not smarter because they know more. They are smarter because they know earlier what not to know.
Orchestration, choreography, and the art of reducing uncertainty
There is another deeper parallel between distributed transactions and query execution: both must choose between centralized control and emergent cooperation.
In saga design, orchestration uses a single coordinator to direct each step. This creates clarity. One component knows the sequence, can decide what happens next, and can trigger compensations if needed. Choreography disperses that control. Each service publishes events after completing its local work, and other services respond. This can scale elegantly, but it can also make the overall process harder to reason about because no single component sees the whole picture.
SQL planners face a similar choice, though less visibly. A query can be written in a way that gives the optimizer a clear route to the answer, or it can be written in a way that forces a less efficient plan. Predicates that are SARGable, meaning they can use indexes efficiently, act like good orchestration. They tell the engine exactly where to start. Non SARGable predicates, by contrast, make the engine discover the answer by wandering.
This suggests a deeper framework: coordination should be explicit where risk is high, and implicit where locality is sufficient. Orchestration is valuable when business consequences are severe, when ordering matters, and when compensations are complex. Choreography is valuable when steps are loosely coupled and the system benefits from decentralization. Likewise, an index is valuable when it dramatically reduces search, but full table scans are fine when the dataset is tiny or the access pattern is broad by design.
The mistake is not choosing orchestration or choreography, indexes or scans. The mistake is pretending these choices are morally fixed rather than situational. Good system design asks a sharper question: where should the system spend its certainty budget?
A certainty budget is the amount of coordination your architecture can afford before it becomes slow, fragile, or opaque. In a saga, you spend certainty when you coordinate multiple services. In SQL, you spend certainty when you ask the engine to inspect more rows than necessary. In both cases, the goal is not zero coordination. The goal is disciplined coordination.
Imagine a restaurant kitchen. The best kitchens do not have every chef asking the head chef for permission before chopping a vegetable. Nor do they let each chef improvise the entire menu. They divide work so that each station can act locally, but they coordinate only the moments that matter, like plating or firing the table. That is a saga. It is also a query plan.
Compensations are not failures, they are the price of speed
One reason developers resist sagas is philosophical. Compensation feels like an apology for not being truly consistent. But that framing is backward. Compensation is not a sign that the system is weak. It is a sign that the system is honest about what it can guarantee.
The same is true of SQL optimization. An index is not a magical answer machine. It is a tradeoff. Indexes speed reads but add overhead to writes. Filtering early reduces work, but only if the filter is selective enough to matter. Avoiding unnecessary sorting helps, but sometimes you genuinely need a sort. Great database design is not about making every operation cheap. It is about making the expensive operations intentional.
Compensation in sagas plays the same role. If a payment was authorized but inventory later fails, you reverse the payment or release the hold. That reversal is not a bug. It is the business equivalent of an execution plan that chooses a narrow index instead of a full scan. You are paying a small, controlled cost later so you do not pay a huge, uncontrolled cost upfront.
This is where many systems go wrong: they want the benefits of distribution without the discipline of reversibility. They allow services to commit locally, but they do not design compensations carefully. They optimize for forward progress and ignore unwind paths. That is like writing a query that runs fast on happy cases but falls apart under real data distribution.
A strong system design culture asks two questions for every important action:
- How does this succeed locally?
- How do we recover locally if later steps fail?
Notice how similar that sounds to SQL tuning advice: use indexes, filter early, reduce result size, avoid unnecessary calculations. Both sets of advice are about making the first decisive move as informative as possible. The sooner a system knows whether it is on the right path, the less waste it creates.
A practical framework: move certainty to the edges
If there is one takeaway that unifies both topics, it is this: push decision making to the edge where the relevant data lives.
In a saga, that means each service should decide what it can decide with its own data. Payment can authorize against payment data. Inventory can reserve against stock data. Shipping can schedule against logistics data. The orchestrator, if present, should not micromanage those internal truths. It should only coordinate the sequence and respond to failures.
In SQL, the same idea means letting the database engine narrow the candidate set as early as possible, using structures that match the data. If you want a fast query, ask the engine to search in a way that aligns with the index order. Do not wrap indexed columns in functions unless you have to. Do not make the engine prove a negative if a positive filter would do. Do not ask it to sort millions of rows if you only need twenty.
This produces a simple decision rule for engineers:
If a choice can be made with local knowledge, make it local. If it must be made globally, make the global step as small and reversible as possible.
That rule is broader than microservices and SQL. It describes good architecture everywhere. The best systems are not those with the fewest moving parts. They are those with the fewest parts that must agree at once.
Think of a library catalog. If you know the author and the year, you go directly to the relevant shelf or index. If the catalog forces you to inspect every book manually, it is still a catalog, but it has failed at its job. Or think of a customs checkpoint. The most efficient checkpoints use documents, categories, and preclearance to reduce manual inspection. They do not eliminate inspection. They compress uncertainty.
That is what both sagas and SARGable queries do. They compress uncertainty into manageable chunks.
Key Takeaways
- Design for local truth first. Let each service or query step solve as much as it can with the data immediately available.
- Treat compensation as a first class feature. If you cannot guarantee global atomicity, invest in clean reversal paths instead of hoping failures are rare.
- Make the expensive part smaller. Use indexes, early filters, and selective predicates in SQL. Use orchestration or choreography only where the business flow truly needs it.
- Push certainty to the edge. The earlier a system can rule out bad paths, the less work it wastes later.
- Optimize for reversibility, not just success. A system is robust when it knows how to fail without leaving a mess.
Conclusion: the best systems do less guessing
We usually talk about distributed systems and SQL performance as separate disciplines. One is about service boundaries and business workflows. The other is about query plans and indexes. But both are really about the same intellectual move: stop asking the system to guess too much at once.
A saga acknowledges that the world is distributed, and therefore certainty must be assembled step by step. A well written query acknowledges that data has structure, and therefore the engine should use that structure rather than ignore it. In both cases, the win is not just speed. It is clarity.
The most durable systems are not the ones that force every question into a single global answer. They are the ones that create a sequence of small, trustworthy answers, each narrow enough to be fast and specific enough to be useful. That is the hidden bridge between transaction design and query optimization.
The next time a workflow feels too hard to coordinate, or a query feels too slow to trust, ask the same question: Where is the system wasting certainty? The answer will usually point to the design change that matters most.
Sources
Hatch New Ideas with Glasp AI 🐣
Glasp AI allows you to hatch new ideas based on your curated content. Let's curate and create with Glasp AI :)
Start Hatching 🐣