Architecture diagrams have a dangerous property: every box looks equally important.
In the product, they are not.
The projects I have worked on occupy very different realities. Saleslyt turns relationship and sales activity into useful decisions. Myotrek connects software to a physical fitness product. A healthcare microservice platform moves information across service boundaries. An offline payment system must reason about a transaction when the network cannot be trusted to answer.
All four can be drawn with APIs, databases, queues, and clients. That similarity is almost useless. The cost of being wrong is different in each one.
The first architecture was the wrong question #
Early engineering conversations naturally start with nouns:
- Which database?
- Monolith or microservices?
- REST, gRPC, or events?
- Which model?
- Which cloud?
Those questions feel productive because they produce decisions. They are often premature.
The better opening question is:
Which uncertainty must this product remove for the person using it?
For a sales product, storing activity is not the outcome. The system must turn scattered activity into a next decision somebody trusts enough to act on. For connected fitness, a technically successful API response is not enough if the experience around the physical movement feels late, confusing, or detached. For healthcare systems, a clean service boundary does not compensate for incomplete context at a clinical boundary. For offline payments, “request timed out” is not an acceptable model of whether value moved.
The architecture begins where the product cannot afford ambiguity.
The real constraint chooses the boundary #
Consider the same design choice—performing work asynchronously—in four contexts.
| Product boundary | Useful async work | Dangerous async ambiguity |
|---|---|---|
| Saleslyt | enrich an interaction, calculate recommendations | silently losing the task a salesperson expects to see |
| Myotrek | aggregate workout history, prepare analytics | delaying feedback that is part of the live physical experience |
| Healthcare services | fan out secondary notifications | separating a clinical decision from required patient context |
| Offline payments | transport and reconcile after connectivity returns | allowing a replay to become a second settlement |
“Use a queue” is not a design. A design says what may be delayed, what must remain ordered, what can be repeated, what must be reconciled, and what the user sees while certainty is unavailable.
This is the dirty part of engineering: the same mechanism can improve one product and damage another.
Correctness includes the operator #
We often write invariants as if only code participates:
one command → at most one committed effectBut production correctness includes the person operating the system. Can support determine what happened? Can an engineer distinguish delayed work from lost work? Can a manager explain the state to a customer without inventing certainty? Can the team reverse a bad release without depending on the path that is failing?
A system that preserves data but gives operators no evidence is technically recoverable and operationally broken.
That changes what “done” means. A background job needs a stable identity, visible state, retry history, and a terminal outcome. An AI recommendation needs its source context, model and prompt version, policy result, and an explanation of what the product will do when confidence is inadequate. An offline command needs an identity that survives transport and a reconciliation view that can answer whether it settled.
The audit trail is not paperwork added after the architecture. It is part of the product’s ability to tell the truth.
The shortcut is not the failure #
Small teams take shortcuts. This is not a confession; it is resource allocation.
The damaging shortcut is the one whose risk remains implicit.
A deliberate shortcut has four parts:
- The constraint: why the ideal path is too expensive now.
- The protected invariant: what the shortcut is still forbidden to break.
- The detection: how the team will know when the compromise stops working.
- The exit: what evidence will trigger replacement.
For example, keeping two domains in one deployable service may be correct while the team is small. The protected invariant could be separate ownership of their data and explicit internal interfaces. The detection could be release coupling and incident frequency. The exit condition could be independent scaling or a team boundary—not an arbitrary user count.
Technical debt becomes dangerous when it has no interest rate anyone measures.
Management is system design with people #
Engineering leadership is often described as making the best technical decision. More often, the work is sequencing decisions so the team can still learn.
An irreversible architecture chosen with weak evidence is not conviction. It is a large bet with poor observability.
I prefer decisions that preserve the next decision:
- define the domain model before splitting services;
- measure queue age before adding more workers;
- record model and policy versions before optimizing AI routing;
- establish command identity before adding automatic retries;
- prove restore before buying a more complicated backup product;
- put one clear owner on an operational boundary before adding another tool.
This is also a management choice. Every abstraction has a teaching cost. Every service has an on-call cost. Every new datastore creates another failure language the team must learn under pressure.
The architecture must fit not only the load, but the organization available to operate it.
What I now ask in a product review #
I no longer start with whether the proposed architecture is elegant. I ask:
Product truth #
- What promise is the user making based on this system’s answer?
- Which wrong answer is worse than no answer?
- When the system is uncertain, what does the user see?
Failure truth #
- Where can the outcome become ambiguous?
- Which effect can repeat?
- What is the smallest blast radius we can enforce?
- How will an operator reconstruct the event without reading raw database rows?
Delivery truth #
- Which part must exist now to learn anything useful?
- Which “scalable” choice creates operational work before it creates value?
- What assumption would make us reverse this decision?
Team truth #
- Who owns the boundary at 2 a.m.?
- Can the team explain and test its recovery path?
- Are we adding a technology because the constraint requires it or because the diagram rewards it?
These questions make architecture less theatrical. They also make disagreement more useful because the team can argue about the constraint instead of defending a favorite tool.
The resolution is a tighter feedback loop #
There is no single architecture lesson shared by Saleslyt, Myotrek, healthcare services, and offline payments. That is the lesson.
The work is to make the product’s unique uncertainty visible, place a correctness boundary around it, and shorten the distance between a real outcome and the team learning from it.
Sometimes the resolution is a stronger transaction. Sometimes it is a queue, a reconciliation worker, or a local snapshot. Sometimes it is removing a service. Sometimes it is changing the user flow so the product stops claiming certainty it does not possess. Sometimes it is a management decision: narrow the scope, assign one owner, and give the team enough time to understand the failure before adding machinery.
Technology, chosen with intent and built—not just advised—means staying close enough to see where the intended system and the lived system diverge.
The diagram is a hypothesis.
The product is what happens to people when that hypothesis meets reality.
Browse all Field Notes · See the projects behind these lessons · Read the engineering essays