The Same Trick Powers Good APIs and Good UI: Make the Invisible Explicit
Hatched by
May 21, 2026
9 min read
3 views
72%
What do metrics and components have in common?
At first glance, a metrics exporter and a UI component look like they live in different universes. One sits near servers, containers, databases, and system internals, turning raw operational state into something Prometheus can read. The other sits in the browser, turning data into interface pieces, passing values from parent to child so the screen can render correctly. Yet both are doing the same profound thing: they make hidden state legible by declaring a contract at the boundary.
That is the deeper idea connecting them. A system becomes easier to understand, observe, and evolve when it stops leaking its internal mess everywhere and instead exposes a deliberate interface. In monitoring, that interface is a metric exposition format. In UI architecture, that interface is a prop. In both cases, the boundary is not an afterthought. It is where complexity is tamed.
This matters because most software pain does not come from a lack of information. It comes from information trapped in the wrong place. Metrics stay buried inside a process. Data stays trapped in a parent component. Teams then compensate with brittle scripts, ad hoc reads, duplicated logic, or tangled dependencies. The result is a system that technically works, but is hard to operate and harder to change.
The real question is not, “How do we collect data?” It is, “How do we design systems so that data crosses boundaries in a form that is simple, predictable, and useful?”
Boundaries are not walls, they are translation layers
One of the most useful mental shifts in software is to stop thinking of boundaries as separators and start thinking of them as translation layers. A boundary does not merely block access. It converts one kind of reality into another kind of representation.
A Prometheus exporter does exactly this. Internal state might live in logs, counters, queues, process memory, or vendor specific APIs. Prometheus does not care about any of that directly. The exporter translates those private realities into metrics such as counts, gauges, and histograms. It is not just collecting data. It is reframing the data so a monitoring system can reason about it.
A Svelte component prop works the same way. A parent component knows something: user information, layout state, theme, a list of items, or a callback. The child component does not need to know where that data came from. It only needs a declared input. The prop creates a narrow, explicit channel through which the parent can speak to the child without exposing its entire internal state.
This is why both patterns are deceptively powerful. They reduce coupling not by removing communication, but by disciplining it. The exporter says, “Here is the limited vocabulary the outside world may use to observe me.” The prop says, “Here is the limited vocabulary this child needs to render correctly.”
Good boundaries do not hide truth. They make truth portable.
That portability is the heart of maintainability. A metric that can be understood outside the process is operationally valuable. A prop that can be understood outside the parent is architecturally valuable. In both cases, the system is healthier when the boundary produces a stable language instead of an accidental leak.
The hidden cost of direct access
Whenever a system allows direct access to internal state, it feels convenient at first. Convenience is the seductive enemy of clarity. It makes every shortcut look like progress, until the system grows and the shortcuts become obligations.
Imagine a service where operators inspect random internal variables by SSHing into machines and grepping memory dumps. The immediate benefit is obvious: you can see everything. The long term cost is worse than hiding data. Every consumer must know too much about the producer. When internals change, all consumers break. Monitoring becomes a scavenger hunt.
Now imagine a component tree where children reach up into ancestors, or where each component quietly depends on a shared object with no declared inputs. Again, this seems flexible. But over time it becomes unclear which data matters, where it came from, and what a component actually needs. Refactoring becomes risky because the interface was never explicit. The child is no longer a child. It is a disguised co owner of the parent’s state.
The pattern is the same in both cases: direct access creates invisible dependencies.
Invisible dependencies are expensive because they are only discovered when they fail. A metric contract makes dependencies inspectable. A prop declaration makes dependencies visible at the point of use. This visibility is not merely aesthetic. It is what allows humans to reason about change.
Think of it like plumbing. You can rip open the wall and route water through any hole you want, but the building becomes impossible to maintain. Or you can use pipes with known diameters, fittings, and valves. The building is less improvisational, but vastly more reliable. A good interface is a pipe, not a hole in the wall.
This is why the best systems do not maximize access. They maximize clarity of access.
Observability and composition are the same design instinct
There is a deeper symmetry here that often goes unnoticed. Exporters are usually discussed as observability tools, while props are discussed as composition tools. But both are expressions of the same design instinct: make the system intelligible by narrowing the shape of communication.
In observability, the question is, “What should the outside world know about this system?” In composition, the question is, “What should this child know about its parent?” These may sound different, but both ask how much of the internal world should leak across a boundary.
A good exporter does not expose everything. Exposing every internal variable would overwhelm Prometheus and create meaningless noise. Instead, it chooses metrics that reflect important operational truths. A good component does not accept everything either. Accepting a giant blob of state makes the interface vague and fragile. Instead, it chooses props that reflect the child’s actual responsibilities.
This leads to a useful framework:
-
Choose the stable language of the boundary. Metrics should express durable truths such as request rate, error rate, or queue depth. Props should express durable needs such as label, size, items, or selected state.
-
Translate, do not dump. Exporters translate internal complexity into a monitoring vocabulary. Props translate parent state into a child vocabulary. Neither should act like a garbage chute for everything available.
-
Expose intent, not implementation. A metric like
active_sessionsis more useful than a raw memory pointer count. A prop likeisOpenis more useful than a miscellaneous bag of flags. Good interfaces tell the consumer what the data means. -
Assume the boundary will outlive the internals. Internal code changes often. The contract should change slowly. That is the point of the boundary.
Once you see this, you can recognize a powerful general principle: every boundary in software is a chance to convert volatility into stability.
A practical mental model: the three questions of a good contract
Whether you are designing a metrics exporter or a component API, ask three questions.
1. What is the outside world trying to do?
Prometheus wants to detect trends, alert on failures, and compare behavior over time. A child component wants to render, respond to user input, or reflect a parent’s state. If you do not understand the consumer’s job, you will expose the wrong shape.
For example, if an exporter emits only raw timestamps and internal IDs, it may be accurate but useless. If a component receives only a generic data object, it may technically be configurable but practically opaque.
2. What is the smallest useful interface?
The best interface is not the smallest possible one. It is the smallest one that still preserves meaning.
A metric should not be vague, but it should not be over specified either. A component prop should not force the child to know the whole parent state, but it should not fragment the interface into dozens of arbitrary fields. The goal is not minimalism for its own sake. The goal is high signal density.
Think of a thermostat. It does not expose the chemical composition of the air, the wiring of the furnace, or the humidity of the room. It exposes one meaningful control and one meaningful observation: temperature. That is a well designed boundary. It gives enough information to act, but not so much that the consumer becomes entangled in internals.
3. What would become dangerous if it leaked?
This is the question that separates mature interfaces from accidental ones. Which details are likely to change? Which details are merely implementation artifacts? Which details would make consumers brittle if they depended on them?
Exporters should avoid depending on ephemeral internal labels that change every deploy. Components should avoid props that mirror every field of a giant domain object when only two fields matter. If the contract exposes too much, it inherits every internal churn event.
The best interface is not a mirror of the system. It is a promise about the system.
That promise is what lets monitoring work across changes and lets components compose without chaos.
Key Takeaways
- Treat boundaries as translation layers, not shortcuts. Convert internal complexity into a stable external language.
- Expose intent, not implementation. A good metric or prop tells consumers what matters, not how the system is built.
- Prefer narrow, explicit contracts over implicit access. Invisible dependencies become expensive when the system evolves.
- Design for the consumer’s job. Ask what the monitoring system or child component is trying to accomplish, then shape the interface around that need.
- Use the boundary to stabilize volatility. Internal details will change. A well designed contract should change slowly.
Why this pattern matters beyond monitoring and UI
Once you understand this pattern, you start seeing it everywhere. APIs, database schemas, message queues, feature flags, event payloads, even company org charts all have boundaries where information must cross from one context into another. The same mistake repeats itself in each domain: people leak internals instead of designing a clean contract.
A great exporter teaches a system how to be watched without being disturbed. A great component teaches a system how to be assembled without being entangled. Both are acts of disciplined communication. Both resist the temptation to make everything accessible. Both understand that software is not just logic. It is a network of promises.
That is the deeper lesson. The most robust systems are not those that reveal the most, but those that reveal the right things in the right shape.
When you design a boundary well, you are not just moving data. You are deciding what kind of knowledge the rest of the system is allowed to have. And in software, as in organizations, that may be the most consequential design decision of all.
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 🐣