Every Solution Is a Symptom
Someone hands you “we need microservices” and your brain starts designing. That reflex is the most expensive habit an architect can have — but always refusing it is its own trap. The routine, and the two cases where you should shorten it.
Someone senior says: “We need to move to microservices.” Or a data lake. Or a rewrite in Go. And something happens in your head before you have decided to think — you start designing it. Boxes, boundaries, a migration order. Within a minute you are useful.
That reflex is the most expensive habit an architect can have.
Solution-first is a very efficient way to be wrong
Solution-first thinking is what happens when someone hands you an answer and you go straight to how. It feels productive, because it is productive — you are drawing, everyone is nodding, the meeting has momentum. It also feels cooperative, which matters more than we usually admit.
None of that momentum tests whether the answer was right. If the solution doesn’t fit the problem, you have just become a very efficient executor of someone else’s mistake — and you spent your own credibility making it look inevitable. When it lands badly a year later, nobody will blame the CEO. They will blame the architect.
Problem-first thinking is the opposite posture: treat every stated solution as a symptom of an unstated problem, and refuse to design anything until you have extracted and quantified that problem. Not as a philosophy — as a literal sequence you run before you allow yourself a single design thought.
1. Convert the solution back into a problem
Ask one question: “If we built exactly this, what would be better in twelve months? What is the thing you would point at?” Then listen, because “microservices” is never one problem. It decodes to at least four, and they are not the same request.
Only one of those is meaningfully answered by extracting services. The others are answered by a deployment pipeline, by bulkheads and timeouts, or — most often — by a conversation. Each decode is a different problem with a different best solution, and the stated solution happens to fit exactly one of them.
2. Quantify it, or it is just an opinion
A problem nobody has measured is a preference with good posture. Force numbers, gently, in the same conversation:
- “Deploys are slow” → how often do you deploy today? How often do you need to? What does the gap cost?
- “It keeps going down” → how many incidents last quarter? How many minutes? What is a minute worth?
- “Teams block each other” → how many hand-offs a week, and how long does each one wait?
The format worth internalising is the quality attribute scenario: when X happens, the system must do Y, within Z. It forces stimulus, response and measure into a single sentence — and a sentence you cannot finish is a problem you have not understood yet.
The shape to write down
“When a carrier changes their file format, we ship the corrected parser to production within two working days, without regression-testing unrelated modules.” Concrete enough to disagree with, specific enough to test against a design. That is the whole point.
3. Do the arithmetic out loud
This is the cheapest, highest-leverage move in the entire routine, and almost nobody does it in the room. Fifty thousand orders a day sounds like a lot. Divide by 86,400.
The moment that number is said out loud, “we need microservices to scale” is finished as a justification — and whatever is still standing afterwards is the real driver, which is exactly what you were trying to find. Do the same for storage, throughput, cost, team count. It takes ten seconds, needs no tooling, and is the most reliable way to separate a real constraint from an imported anxiety.
4. Only now, generate options — at least three
Three is the minimum, because two is a false binary and one is a decision you already made. The set has to include the boring option — fix the deployment pipeline, keep the monolith — and the do-nothing option, priced honestly rather than dismissed.
Then score them against the numbers from step 2. Not against what is current, not against what is on the conference circuit, and not against what the person in the room already said they wanted.
Where this rule breaks
Everything above is right, and running it religiously will still get you into trouble in two specific ways. The real skill is not running the routine — it is knowing when to shorten it.
Some solutions are constraints in costume
“We are moving to Azure,” from someone who signed a three-year commitment last week, is not a hypothesis you get to falsify. Neither is a board-level decision, a regulator’s data-residency requirement, or an acquisition you have not been told about yet.
Run steps 1 through 4 on those and you will produce a beautiful analysis proving the boring option wins — two weeks after everyone else in the room knew the decision was made. You don’t look rigorous. You look like you weren’t listening.
So there is a step 0, and it is one question: is this settled, or are we still choosing?
If it is settled, your job flips. You are no longer asking what problem we are solving; you are finding the cheapest correct way to live inside the constraint, and naming precisely what it costs us. That is still architecture. It is just a different job — and doing it well without sulking buys you the credibility you will need the next time something genuinely isn’t settled.
The interrogation itself has a cost
The full routine on something expensive and hard to reverse is obviously worth it. The same ceremony applied to “should we put a cache in front of this query” turns you into a tax, and an architect who gets routed around has no leverage at all — which is the exact failure you were trying to prevent.
Scale the routine to reversibility × cost. Cheap and reversible: let them build it and watch what happens — the build is the experiment, and it will produce better data than your analysis would. Expensive and one-way: run everything, then slow down further.
Two ways to sharpen the routine
The stated solution is evidence — don’t throw it away
Decoding “microservices” into a problem is right, but keep the original word. It is telling you something real: what their peers said over dinner, what the board asked last month, what they are afraid of being caught not doing. Discard the solution entirely and you lose all of that signal.
Sometimes the honest decode is “I read about this and I’m scared we are behind.” That is a genuine problem with a genuine solution. It simply isn’t an architecture solution — and the most valuable thing you can do is recognise it, say it kindly, and address the actual thing, usually with a demo, a competitor benchmark, or ten minutes of the arithmetic above.
Unmeasurable is not the same as unreal
Step 2 is the strongest part of the method and the easiest to corrupt, in two directions.
First, people invent numbers to fill the template. A fabricated figure is worse than an admitted unknown, because it survives into the decision document carrying false authority, and six months later nobody remembers it was a guess.
Second, and more common: anything that resists measurement gets scored zero and quietly vanishes from the comparison. Hiring. Morale. Key-person risk. Optionality. These are real, and they are frequently decisive. When you cannot measure one, write “I can’t put a number on this, and here is why it matters anyway” and leave it in the table unscored. Deleting it is not rigour — it is rigour theatre.
The tell
There is a reliable signal for whether you skipped all of this. Look at your first sentence in the design discussion.
| If your first sentence contains | It should have contained |
|---|---|
| “microservices”, “Kubernetes”, “event-driven” | “50,000 a day — that’s 0.6 a second” |
| “we should move to…” | “how often does that actually happen?” |
| “let me sketch the service boundaries” | “how many incidents was that last quarter?” |
| a technology name | a number |
And the mirror of it, which is newer and just as useful: if your first sentence is a question, and the decision was settled last quarter, you skipped step 0.
Why this is the architect’s job specifically
I have argued before that the most expensive code is the code you don’t design, and that architecture can’t be outsourced to an LLM. This is the layer above both: the most expensive architecture is the one that correctly solves a problem nobody actually had.
Everyone else in the room has a reason to skip the decode. Engineers want to build the interesting thing. Executives want to announce the credible thing. Vendors want to sell their thing. The architect is the only person whose job includes asking what problem are we solving and would this actually solve it — and having the numbers ready when the answer is no.
Every stated solution is a symptom. Decode it first — then decide how much of the routine it deserves.