The Strange Rule Shared by Good UIs and Good Systems: One Thing Must Own the Truth

tfc

Hatched by tfc

May 12, 2026

10 min read

88%

0

The hidden fight behind every “simple” app

Why do so many software systems become complicated exactly when we try to make them easier to use? A button in one place changes a panel in another, a form echoes stale values, a background job updates something no one seems to own, and suddenly everyone is asking the same question: where does the real state live?

That question sounds technical, but it is really a design question about authority, coordination, and the cost of duplication. Whether you are building a user interface or a distributed architecture, the same tension keeps appearing: should related things keep their own copy of the truth, or should one place own it and others merely listen?

The surprising answer is that the best designs often follow the same rule in both worlds. If two things must always change together, they should not each pretend to be independent. Put the truth somewhere specific, and make everything else react to it. In a UI, that means lifting state up. In a system, that means using events and a message bus to separate decision from reaction.

What looks like a small implementation detail is actually a deep principle: coordination is the real cost of software.


Duplication feels local until it becomes political

Duplicated state is seductive because it feels fast. A component keeps its own copy of a value, a service stores its own version of a record, a module updates its own cache. At first, this looks like freedom. Each part can work on its own, and no one has to ask permission.

But duplication has a hidden demand: every copy must stay aligned. The moment one copy is updated and another is forgotten, the system begins to lie. A checkbox says one thing while a sidebar says another. An order is marked paid in one service but still pending in another. The code still runs, but trust begins to erode.

That erosion matters because users do not experience your architecture. They experience inconsistency. They do not care whether the bug came from a missed prop, a stale cache, or an event handler that ran out of order. They care that the system contradicted itself.

This is why the principle of a single source of truth is not just about cleanliness. It is about preserving coherence under change. One owner means one decision point. One decision point means fewer contradictions. And fewer contradictions means a system that is easier to reason about, test, and evolve.

A software system becomes fragile not when it has too little structure, but when it has too many places where the same truth can be edited.


The real question is not where data lives, but who is allowed to decide

It is easy to think that “state” is just data. But in practice, state is authorization. To own a piece of state is to have the power to define its current reality. That is why lifting state up matters so much in UI design: the component that owns the value becomes the place where consistency is enforced.

Consider two text inputs that must always match, such as a “password” and “confirm password” field. If each field owns its own value, the interface cannot reliably compare them because the comparison itself becomes a coordination problem. If a parent owns both values and passes them down, the parent becomes the referee. The children are no longer competing versions of reality. They are simply views over a shared decision.

That same pattern appears in architecture. A function or service should not try to do two unrelated jobs at once. If you cannot describe what it does without using words like “then” or “and,” you may have given it multiple responsibilities. That is a clue that it is holding too many decisions in one place.

But there is an even deeper lesson here. The purpose of a central owner is not to make everything centralized. It is to make ownership explicit. Once ownership is explicit, you can create boundaries: who decides, who observes, who reacts, who recomputes. Complexity does not disappear, but it becomes legible.

This is why the best systems often feel both centralized and decentralized at once. The truth has a home, but behavior is distributed.


Events turn control into choreography

A message bus or event loop changes the shape of a system by separating causation from coordination. Instead of one component directly commanding many others, it emits an event and lets interested parts respond. This is closer to an actor system, a UI event loop, or a carefully designed reactive interface than to a monolithic procedural flow.

That difference matters. In direct control, one part must know who to call, in what order, and what dependencies exist downstream. In event-driven coordination, the emitter says what happened, not what should happen next. That creates a useful boundary. The initiator handles the decision, and observers handle the consequences.

This is not the same as chaos. Good event systems are not “anything can happen anywhere” systems. They are systems with clear ownership and loose coupling. The bus does not erase structure, it relocates it. Instead of wiring every participant to every other participant, you give them a shared language for change.

Think of a train station announcement system. The station does not physically drag every traveler to the correct platform. It makes one announcement, and the right people respond. The announcement is the event. The travelers are the subscribers. The station does not need to know each individual route in detail, but it must know the rules of the system.

That is the key insight: events work best when they describe facts, not instructions. Facts can be shared. Instructions tend to create entanglement.


Why “lifting state up” and “publishing events” are the same move

At first glance, React state management and message bus design seem like different disciplines. One is about rendering interfaces, the other about coordinating components or services. But they solve the same problem from opposite directions.

In React, when two components must stay in sync, the answer is to move the shared value to the closest common parent. That parent owns the state and passes it down. The architecture is hierarchical, so ownership follows the tree.

In an event-driven system, when multiple parts need to respond to a change, the answer is often to have one part publish a fact onto a bus. Other parts subscribe and react. The architecture is temporal, so ownership follows the sequence of events.

In both cases, the same design law applies: the truth should be stored where decisions are easiest to verify, and shared where reactions are easiest to compose.

You can think of this as a two step model:

  1. Choose an owner for the truth.
  2. Choose a broadcast mechanism for the consequences.

This model prevents a common mistake: confusing ownership with access. Not everyone who needs to know the truth should be allowed to edit it. Not everyone who reacts to a truth should be forced to understand how it is stored. A parent owns state, children consume it. A publisher emits an event, subscribers respond to it.

Once you see this, the apparent gap between UI design and architecture shrinks. Both are about building systems where one thing decides, many things adapt.


A practical mental model: authority, observation, reaction

Here is a framework that helps connect these ideas without getting lost in implementation details.

1. Authority

Ask: who is responsible for defining the current value or outcome?

If the answer is ambiguous, the system will drift. Authority should be singular for any piece of truth that must remain consistent. In UI state, that might be the nearest parent. In a service architecture, that might be the domain aggregate or workflow coordinator.

2. Observation

Ask: who needs to know that the truth changed?

Observation is not ownership. A component may display a value without controlling it. A service may react to an event without making the decision that caused it. Observation is cheap when the truth is singular and expensive when the truth is duplicated.

3. Reaction

Ask: what should happen next, and does it need to happen synchronously?

Some responses are just render updates. Others are side effects, notifications, logging, or downstream workflows. If you force all reactions into the same place as authority, the code becomes brittle. If you let reactions scatter without a central fact, the system becomes incoherent.

This model helps diagnose bad design quickly. If a component both owns a value and mirrors it elsewhere, ask whether you have mixed authority with observation. If a service both emits a fact and directly orchestrates every response, ask whether you have confused reaction with command.

The result is a system with fewer hidden loops. You can trace the line from truth to effect without chasing duplicated state across layers.


The deeper payoff: consistency becomes cheaper than cleverness

Many teams optimize for immediate convenience. Local state feels easy. Direct calls feel clear. Shared copies feel performant. But these choices often push complexity into the future, where it returns as bugs, synchronization logic, and fear of change.

The architectural win of a single source of truth is that it makes consistency cheap. The win of event-driven coordination is that it makes reaction cheap. Put together, they reduce the need for fragile, hand-built agreement between parts of the system.

This has an important cultural consequence too. Teams often debate whether to centralize or decentralize, as if they were opposites. They are not. The best systems centralize truth and decentralize behavior. That is a much subtler and more powerful balance.

If you centralize behavior, every change becomes a bottleneck. If you decentralize truth, every change becomes a negotiation. The sweet spot is to have a clear owner for each unique fact, then let the rest of the system listen and adapt.

That is why “single source of truth” is not a dogma. It is a way to reduce the number of places where reality can fork. And “message bus” is not an abstraction for its own sake. It is a way to let the consequences of reality spread without forcing everyone to share the same implementation.


Key Takeaways

  • Give every unique piece of state one owner. If two parts must always agree, do not let them maintain separate copies.
  • Separate truth from reaction. One component or service should decide what is true, while others react to that truth.
  • Use events for facts, not instructions. Publish what happened, not a detailed script of what everyone else should do next.
  • If your function reads like “do this and then that,” inspect its responsibilities. Multiple responsibilities often hide multiple ownerships.
  • Prefer explicit coordination over accidental synchronization. Hidden duplication is usually where bugs are born.

Conclusion: the best systems do not share everything, only the right thing

It is tempting to think that good software is about making everything accessible everywhere. But that instinct often creates the very inconsistency it hopes to avoid. The stronger principle is simpler and more demanding: share the truth once, then let everything else adapt to it.

That is why lifting state up in a UI and publishing events in a system are not separate tricks. They are expressions of the same design wisdom. A healthy system does not ask every part to be a miniature authority. It gives one part the responsibility to know, and many parts the freedom to respond.

In that light, architecture is less about data movement than about moral clarity. Who gets to decide? Who merely observes? Who reacts? The elegance of a system often depends on answering those questions honestly.

And perhaps that is the deepest lesson here: complexity is not reduced by hiding state in more places, but by making ownership unmistakable. Once truth has a clear home, the rest of the system can finally stop pretending to be the source of reality and start doing what it does best, listening, rendering, reacting, and evolving.

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 🐣