Decisions in a software system differ by the cost of their going wrong, so they need different levels of care. This is the reason we separate architecture from design. In this note, I used architecture as a means of deciding where either blast radius or reversal cost is high.
Software architecture is about all the important decisions where going wrong will have a high blast radius or a high reversal cost, whereas software design concerns decisions that have a lower blast radius and reversal cost than architectural ones.
Blast radius is how many parts of the system, teams or external consumers are affected. Reversal cost is how hard or expensive it is to change later, including data migration and external contracts.

Examples:
Choosing MongoDB vs PostgreSQL for a service is an architectural decision because of high reversal cost. We may reduce the code-level cost to an extent by putting a data access layer in front, but differences in consistency, transactions and data modelling remain, and so does the data migration. So it stays architectural.
Deciding the cache key design for a service is a software design decision because no other system depends on it, so changing it has a low blast radius and a low reversal cost.
The event schema we publish to external partners over webhooks is an architectural decision, even though it is low-level. Partners depend on it, so changing it has a big impact. This shows "high level" is not the real test.
How does design relate to architecture?
Design happens inside the boundaries that architecture sets. Quality requirements (for example, 1000 req/sec for search) push decisions up into architecture, but the decisions that satisfy them can be either. Splitting search into its own service is architecture; choosing the cache key shape inside it is design.
The line is also relative to scope. A service boundary is architecture for the org, while module structure inside a service is architecture for the team owning it.
When does a design concern become architectural?
A design concern can become an architectural concern if, for some reason, its blast radius and/or reversal cost has increased.
Assume the cache key (previous example 2) started being used by another service. The blast radius as well as the reversal cost suddenly increase, and hence the cache key becomes an architectural concern. This usually happens silently, when another team starts depending on it and nobody announces it.
It can also go the other way. If we reduce the blast radius, for example by putting it behind an interface, an architectural concern can drop back to design.
How does a requirement translate to architecture and design decisions?
When we work on a requirement, we first identify if it has any architectural concerns. Mostly these come from non-functional needs (latency, availability, scale, security), and from functional needs only when they imply structure. Based on that we create a fence within which design has to be done.
Sometimes design alone is not enough to satisfy the requirement, because the cause sits outside the fence, for example, a slow external provider in the critical path. Then we have to change the architectural decision too, so it's not always a top-down approach, the impact also flows bottom-up.
Example: search at 1000 req/sec with p99 under 200 ms

Consider the situation: a load test shows p99 of 800 ms because every search fans out live to four external providers.
Design fixes keep the contract unchanged: parallel calls, tighter timeouts and circuit breakers, as long as the response shape stays the same.
Fixes that change the contract are architectural: returning partial results when a provider is slow, or prefetching and caching data that was never stale before.
If one provider's p99 is already near 700 ms and it sits in the critical path, tuning our side cannot go below it. Only taking it off the critical path (removing it, or no longer waiting for it) will bring the latency down. So this needs an architectural change, and design alone is not enough. This is the latency floor.
A TTL cache is a design decision if the system already tolerates staleness, and an architectural one if it introduces staleness where there was none.
Where the model gets tricky in real systems
The dials drift
Blast radius and reversal cost are not fixed when we make a decision. They grow over time as others start depending on it, so the score we gave it back then can be stale today. If we don't have proper checks and balances for catching architecture in design disguise, we accidentally treat it as cheaper to change than it is. Hence, if we catch it early, it is cheaper to shrink the blast radius.
Reducing reversal cost on purpose
We can make some decisions cheaper to reverse by using stable interfaces, versioned contracts, and by delaying choices until we know more. But these efforts have real costs, and they feel wasted if the change never happens. Take the data access layer from example 1. If we build it only for a database swap that may never come, it is wasted effort. If we build it for everyday benefits like easier testing and containment1, then a swap becomes a bonus.
Why misclassification is expensive?
If we treat an architectural decision like a normal design decision, nobody reviews it properly and it gets locked in by accident. If we treat a design decision like architecture, teams wait for approvals and slow down. So the effort should match the risk: a normal code review for design, and a written decision with cross-team review for architecture.
Coordination is part of reversal cost
Changing something is not only a technical job; it also needs people to agree and plan together. An interface between two teams is architectural because both teams must coordinate to change it, not because the technology is hard. So the same interface can be a design decision when one team owns both sides, and an architectural one when two teams depend on it. The org structure decides where the line falls (this is Conway's law2 at work).
Example: service A publishes events that only service B, in the same team, consumes. Changing the schema is a design decision. When service C from another team starts consuming it, the blast radius grows to include another team, and the reversal cost grows because that team must agree and schedule the change. Now the schema is architectural. The team should treat it as a versioned, tested contract: write the schema down, agree change rules (for example, only additive changes), add contract tests, and name an owner.

To classify or not to classify
The main reason to classify decisions is communication, not technique. If a decision affects multiple teams and stakeholders, it deserves a short written decision record, and we should keep an eye on it so it doesn't drift and become expensive.
But the moment we start arguing over the label ("is this architecture or design?"), the distinction has stopped being useful. The label matters very little. What matters are the questions behind it: who is affected, and how costly is it to undo? If we keep answering those, we don't need a label.
This distinction also doesn't matter much in a throwaway prototype, where everything is cheap to change. It starts to matter as soon as the prototype becomes real software.
There are three common ways to draw the line, and the first is the one we used here.
Cost of change: defined by people like Martin Fowler and Ralph Johnson, where architecture is the important stuff, the decisions that are hard to change. It guides us on which decisions need care.
By structure: people like Bass, Clements and Kazman define architecture as the structures you need to reason about the system: the elements, their relations and their properties. It is a good way to document and analyse a system, but it doesn't tell you which decisions need your attention.
By zoom level: models like C4 let us see a system from system context down to containers, components and code. It is an easy way to visualise and understand a system, but it misses things like the webhook schema, which is low-level but very significant.
Important: We should use cost to decide process, structure to document, and zoom level to communicate. Hence all of these three mechanisms have their own importance and can be used for specific needs.
Further reading
Grady Booch, "Architectural Organizational Patterns", IEEE Software, 2008. Architecture as the significant design decisions, where significant is measured by cost of change.
Martin Fowler, Who Needs an Architect?, IEEE Software, 2003. Quotes Ralph Johnson on architecture being the important stuff, and the decisions that are hard to change.
Bass, Clements and Kazman, Software Architecture in Practice. The "structures needed to reason about the system" wording is from Clements et al., Documenting Software Architectures: Views and Beyond (2nd edition, 2010).
D. L. Parnas, On the Criteria To Be Used in Decomposing Systems into Modules, Communications of the ACM, 1972. The root of containment and stable interfaces.
Mary and Tom Poppendieck, Lean Software Development (2003). The "last responsible moment" (summary).
Michael Nygard, Documenting Architecture Decisions, 2011. Where ADRs started.
Jeff Bezos, Amazon shareholder letters. Type 1 and Type 2 decisions (one-way and two-way doors).
Melvin Conway, 1968. See Fowler on Conway's law.
Simon Brown, The C4 model.
Footnotes
Containment helps in isolating messy details for example, keeping SQL and ORM quirks within a data access layer so business logic only requests outcomes (e.g., "find open orders"). It keeps changes local and doesn't let details leak, which would force global changes. Containment helps in shrinking the blast radius.
Conway's law: The structure of a system ends up copying how the people who build it communicate. If two teams talk to each other only through a formal interface, the software tends to have a hard boundary at the same place. It comes from a 1968 paper by Melvin Conway. Don't fight it. Accept it, or shape the teams to get the architecture you want (the "inverse Conway maneuver").
