Why Distributed Systems Need a Grammar, Not Just Rules

Kai Nguyen

Hatched by Kai Nguyen

Apr 23, 2026

10 min read

74%

0

The Hidden Problem Is Not Failure, It Is Meaning

What if the hardest part of a distributed system is not handling errors, but agreeing on what a result even means?

That is the quiet tension underneath both transaction coordination and SQL analysis. In one world, services need a way to decide whether an order is truly complete when inventory, payment, shipping, and notification all live in different places. In the other, analysts need a way to decide whether a number is truly comparable when rows belong to different groups, time windows, or partitions. In both cases, the real problem is not computation. It is coordination of meaning across boundaries.

We often talk about distributed systems as if they are primarily about infrastructure: queues, databases, retries, locks, CTEs, partitions, orchestrators. But those are just the mechanics. The deeper question is: how do you build a system that can preserve intent when no single component sees the whole picture?

The answer, surprisingly, looks similar whether you are managing microservices or writing SQL. You do not begin with a giant global operation. You begin by decomposing the problem into local units of truth, then you establish a language for recombining them.


Local Truth Is Cheap, Global Truth Is Expensive

Traditional ACID transactions promise a comforting illusion: one action, one truth, one commit. But the moment your application spans multiple services, that illusion breaks. Each service has its own database, its own latency profile, its own failure modes, and its own responsibility. You can no longer demand one perfect all-or-nothing move without paying a huge coordination cost.

The Saga pattern accepts this reality. It replaces one global transaction with a chain of local transactions, each executed inside a single service. If something goes wrong, earlier steps are not rolled back in the classical sense. Instead, they are undone through compensating actions. This is a profoundly different philosophy. It says: preserve progress where possible, and repair meaning when necessary.

SQL has a similar philosophy hiding in plain sight. A CTE creates a named intermediate result. A PARTITION BY clause tells a window function what belongs together. Ranking functions let you compute order inside a subgroup rather than pretending the whole table is one undifferentiated mass. These are not just query tricks. They are ways of establishing local truth before attempting any broader interpretation.

The most robust systems do not force a single global answer too early. They preserve smaller truths, then compose them carefully.

This is why both Saga design and advanced SQL become powerful when you stop thinking of them as tools for control and start seeing them as tools for structuring partial agreement.

Imagine a checkout flow. Payment is authorized, inventory is reserved, shipping is scheduled, and an email is sent. In a monolithic database, you might insist that the entire sequence be one atomic commit. In a distributed system, that becomes brittle. If shipping fails after payment succeeds, the system must decide whether to cancel payment, delay shipment, or retry. That decision is not merely technical. It encodes business semantics.

Now imagine a SQL report that ranks users by monthly revenue, but separately within each region. If you forget PARTITION BY, you get a global ranking that is technically valid but semantically wrong. The query runs, the numbers look clean, and the conclusion is misleading. That is the SQL equivalent of a distributed transaction that succeeded technically but failed conceptually.

The lesson is the same in both domains: correctness depends on boundaries.


Orchestration and Choreography Are Two Ways of Writing a Sentence

Saga implementations usually come in two styles: orchestration and choreography. The distinction is often presented as an architectural choice, but it is more revealing than that. It is really a question of whether you want a central narrator or a distributed conversation.

In orchestration, one component directs the others. It knows the steps, the order, and the compensation logic. This gives clarity, observability, and control. It is like a conductor with the score in hand. The downside is that the conductor becomes a bottleneck, and the system can become overly dependent on one source of coordination.

In choreography, each service responds to events and publishes the next event after completing its work. No single agent owns the whole process. This can improve decoupling and scalability, but it also makes the system harder to understand. The process emerges from interactions rather than being declared in one place.

SQL offers a similar contrast in miniature. A CTE is orchestration. It gives a name to a stage in the logic and makes the flow explicit. A window function over partitions is closer to choreography. You define the local context, and the calculation happens across the rows that happen to belong there. The computation is distributed across a structured field, not centralized into a single step.

The important insight is that both patterns are ways of writing a sentence about the world.

A good sentence needs grammar. Without grammar, words are just noise. In a distributed system, events are words, local transactions are clauses, and compensation is punctuation. In SQL, CTEs, partitions, and window functions serve the same role. They give the system a grammar for expressing multi-step intent without pretending the world is simpler than it is.

This matters because many engineering failures are really failures of grammar. Teams use the right parts but connect them in ways that do not express the right semantics. They build event-driven systems with no clear narrative. They write queries with correct syntax but incorrect grouping. In both cases, the computer does exactly what was asked, not what was meant.

A useful mental model here is the difference between execution order and semantic order.

  • Execution order is what happens first in time.
  • Semantic order is what must be understood first in meaning.

Saga orchestration tries to make execution order visible. Choreography spreads execution order across the system but still requires a shared semantic order. SQL windows let you compute over rows in one semantic grouping while the physical execution may happen differently. Great systems separate these two concerns instead of confusing them.


Compensation Is Not Failure Handling, It Is Design for Reversibility

The word compensation is easy to misunderstand. It sounds like a fallback, a patch, a cleanup script for when things go wrong. But in a mature distributed system, compensation is not an afterthought. It is part of the original contract.

That is a very different way to design software. If you treat rollback as an emergency feature, you will build processes that are fragile under failure. If you treat reversibility as a first-class property, you begin asking better questions:

  • What state changes can be safely reversed?
  • Which side effects are permanent?
  • Which operations need confirmation before commitment?
  • What is the acceptable window of inconsistency?

These same questions have SQL analogues. A CTE can isolate a transformation so you can inspect it before using it downstream. A ranking function can compute order without mutating the underlying data. Window functions can give you derived meaning without destroying the base relation. SQL is full of reversible thinking, even when it is not explicit.

That suggests a broader principle: robust systems are not those that never fail, but those whose failures remain interpretable.

A payment authorization that can be voided is better than a payment capture that cannot be explained. A reservation that times out cleanly is better than one that leaks ambiguity into downstream services. A query that exposes its partitions is better than one that hides its grouping assumptions. In each case, the system earns trust by making its intermediate state legible.

Think about a hotel booking flow. A room is reserved, then payment is processed, then confirmation is sent. If the confirmation service fails, the reservation should not vanish into a black box. The system should know whether to retry, compensate, or escalate. Similarly, in SQL, if you are calculating revenue by cohort, you need to know whether the cohort definition is stable, whether rows can move between groups, and whether your final aggregate is describing a durable reality or a temporary slice.

The deeper connection is that compensation and partitioning both protect against a common error: confusing provisional structure with final truth.


The Real Skill Is Not Transactions or Queries, It Is Boundary Thinking

The most underrated skill across both engineering and analytics is not syntax. It is boundary design.

Boundary thinking asks: where should meaning be local, and where should it be shared? What should be computed in isolation, and what should be reconciled later? Which facts are authoritative within a service, and which must be inferred across services? Which rows belong together for this calculation, and which should be excluded even if they appear adjacent?

This is why senior engineers often seem obsessed with details that look small from the outside. They care about event names, idempotency, compensation semantics, partition keys, and intermediate results. These details define the shape of truth in the system. Get them wrong, and everything downstream becomes technically correct but contextually false.

A practical way to think about it is to divide every complex system into three layers:

  1. Local validity: Does each service or query step make sense on its own?
  2. Connection logic: How are local results passed, grouped, or narrated?
  3. Recovery logic: If the chain breaks, how is meaning repaired?

Saga patterns are a direct answer to all three layers. SQL CTEs and window functions are, in a smaller but surprisingly analogous way, a direct answer to all three layers. The CTE creates local validity. The partition or window defines connection logic. The ranking or aggregate result surfaces meaning in a recoverable, inspectable form.

This is why data modeling and distributed architecture are closer than they first appear. Both are disciplines of making boundaries explicit.

When boundaries are vague, systems become magical in the worst sense. They seem to work until they do not, and then no one can explain why. When boundaries are explicit, systems become debuggable, auditable, and evolvable. You can reason about them even under partial failure.

That is not just a technical benefit. It is an organizational one. Teams that understand boundaries can distribute responsibility without losing coherence. Teams that ignore boundaries centralize blame, obscure semantics, and rely on heroics to paper over design gaps.

Distributed systems do not fail because they are distributed. They fail because the meaning of state was never distributed as carefully as the code.


Key Takeaways

  • Treat local operations as first-class truths. Do not wait for the whole system to agree before making progress. Design each step to be valid on its own.
  • Define compensation as part of the contract. If a step can fail, decide in advance how its effects can be reversed or neutralized.
  • Use boundaries to encode meaning. In architecture, that means service ownership and event flow. In SQL, it means CTEs, partitions, and window definitions.
  • Separate execution order from semantic order. The sequence in which things happen is not always the sequence in which they should be understood.
  • Prefer interpretable failure over opaque success. A system that can explain its intermediate state is more trustworthy than one that merely returns a final answer.

Conclusion: The Best Systems Speak in Parts, Not in Monoliths

We often praise simplicity, but in distributed environments simplicity rarely means fewer moving pieces. It means fewer ambiguities. That is the real unifying lesson here. Whether you are designing a Saga or writing a query with partitions and window functions, you are not just moving data. You are shaping the grammar by which a complex system can remain intelligible.

The goal is not to eliminate boundaries. The goal is to make them meaningful.

A system that understands boundaries can recover. It can explain itself. It can proceed locally without lying globally. And once you see that, you start to recognize a powerful pattern across software design, data analysis, and even decision making: the most reliable forms of intelligence do not insist on a single perfect view. They build a network of partial views that can still agree on what matters.

That is not merely a technique. It is a philosophy of computation: truth, in distributed worlds, is something you compose.

Sources

← Back to Library

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 🐣