open atlas
↑ Back to track
Architecture Patterns ARCH · 00 · 01

What architecture actually is

Architecture is the set of decisions that are expensive to change — not diagrams, not patterns. Design and architecture occupy different cost horizons. 'Best practice' is a category error: context determines fit, not a pattern name.

ARCH Middle ◷ 18 min
Level
FoundationsJuniorMiddleSenior

A startup ships a monolith. It works. Two years later the team has grown to thirty engineers and every feature takes six weeks because everything touches the payments module. The CTO calls it an “architecture problem” — but nobody ever decided to couple payments to everything. They just never decided not to. That coupling accumulated one small shortcut at a time, each reasonable in isolation, until reversing it would require rewriting half the system. The team had been making architectural decisions all along — they just hadn’t been naming them as such.

The cost-of-change definition

The most useful definition of software architecture is not about boxes-and-arrows diagrams or named patterns. Ralph Johnson put it simply: architecture is the decisions that are hard to change. Martin Fowler refined this to the decisions that, once made, cost more and more to reverse as the system grows around them.

This framing immediately separates architecture from ordinary design. If you choose a variable name today and decide tomorrow you want a better one, a rename refactor takes twenty seconds. That is design — low cost of reversal. If you choose to keep your billing logic inside your HTTP handler and twelve months later decide you want to serve the same billing from a background job, a mobile app, and a partner API, you have a structural problem that will require weeks of risky surgery. That is architecture — the high-cost-of-reversal decision.

The implication is uncomfortable: you are making architectural decisions constantly, whether or not you call them that. The question is not whether to make them, but whether to make them intentionally.

Design vs architecture: two different horizons

Design and architecture are not two levels of a hierarchy; they operate on different time horizons and cost envelopes.

Design is the shape of a solution within an already-settled structural context. Which class holds this method? How should this function be named? How does this module’s API look? These choices matter for readability and correctness, but they can be revised without structural surgery. Design decisions live inside the boundaries that architecture has drawn.

Architecture draws those boundaries. Where does the boundary between the billing domain and the shipping domain sit? Does each domain own its database schema, or do they share one? Can the ordering service call the billing service synchronously, or must it go through an event? These decisions propagate structurally — they constrain every design decision made downstream of them.

The confusion arises because the same technology can be either. Choosing PostgreSQL as your database for a prototype is a design decision — you can switch. Choosing PostgreSQL as the single shared database whose schema is directly queried by eight services, each assuming specific table structures, is an architectural decision. You have embedded the assumption so deeply that the database cannot be replaced without replacing all eight services at once.

Why this works

Why does the distinction matter in practice? Because teams treat the two kinds of decisions differently. Design decisions get revised in code review. Architectural decisions get made in conversations that may not be recorded anywhere. This asymmetry is how coupling silently accumulates: nobody says “today we are making an architectural decision to couple billing to the HTTP layer.” They say “let’s just call the billing function directly from the handler for now” — a sentence that sounds like a design decision but is, in context, an architectural one.

The “best practice” category error

“Use microservices” is a best practice. “Use hexagonal architecture” is a best practice. “Separate your business logic from your infrastructure” is a best practice. These prescriptions appear in books, talks, and engineering blogs, and they are not wrong — they describe patterns that solved real problems for specific teams in specific contexts. The error is treating the prescription as context-free.

Best practices are solutions to forces. The hexagonal architecture pattern exists because the force “I need to test my business logic without a database” and the force “I need to run the same application from an HTTP server, a CLI, and a message queue” exert real pressure. If those forces are present in your system, hexagonal architecture is a good fit. If your system is a CRUD API that will never have those forces, hexagonal architecture adds layers, interfaces, and indirection without corresponding benefit. It is not “best” for you — it is overkill.

The correct question is never “what is the best practice?” It is “what forces is my system subject to, and what structures answer those forces?” This is the frame that the rest of this track uses. Every pattern we examine will be presented as the answer to a named set of forces — and the tradeoffs it makes in the process.

What architecture is not

Two things commonly masquerade as architecture:

Diagrams. A diagram describes an architecture — it is not the architecture. Teams often confuse the artifact with the reality. The architecture is the actual coupling structure in the codebase; the diagram is a model of it. When the diagram says “billing is a separate service” but the code shares a database schema with ordering, the diagram is wrong and the coupling is the reality.

Up-front design. Architecture does not require a design phase before a line of code. Many of the most durable systems were architected incrementally — each decision made when the forces were understood well enough to make a good one. What architecture requires is intentionality: recognizing which decisions are expensive to change, making them deliberately, and recording the reasons. That can happen at any point in a project.

lesson.inset.note

The practical test for whether a decision is architectural: ask “if I need to reverse this in twelve months, how much of the codebase will I have to touch?” If the answer is “most of it,” the decision is architectural regardless of whether it was labeled as such. This test also reveals why apparently minor decisions — like whether a service exposes its internal data model as its public API — become architectural as the system grows consumers.

Quiz

A team decides to put billing logic directly inside HTTP route handlers. Six months later, they need billing from a background job and a partner webhook. What makes this an architectural decision rather than a design decision?

Quiz

Your team is building a CRUD API for a simple internal tool that will never have multiple entry points and has no testing pressure on the business logic layer. A senior engineer suggests adopting hexagonal architecture. What is the most accurate response?

Quiz

An up-to-date architecture diagram shows billing as an isolated service. The actual code has billing logic called directly from the order service's repository layer via a shared internal library. Which is the real architecture?

Recall before you leave
  1. 01
    How do you distinguish an architectural decision from a design decision?
  2. 02
    Why is 'best practice' a category error when applied to architectural patterns?
  3. 03
    If the architecture diagram and the code disagree, which is the real architecture?
Recap

Architecture is the set of decisions that grow more expensive to reverse as the system matures around them. This separates it from design — which operates inside an already-settled structural context and remains cheap to revise. The distinction is not about diagram level or file count: a single-line decision that couples billing to the HTTP layer is architectural; a multi-file rename refactor is not.

Named patterns — hexagonal, clean, DDD, CQRS — are answers to specific forces. They are not best practices to follow universally; they are solutions that are worth the complexity they introduce only when the forces they answer are actually present. Adopting them without the forces is speculative architecture that creates overhead without corresponding benefit.

The diagram is not the architecture — the code is. Intentions, design documents, and box-and-arrow pictures describe the architecture someone wanted. The actual coupling in the codebase is the architecture that exists. Throughout this track, we will name the forces first and the structural answers second — that is the only way to reason about whether a given structure is right for a given system.

Practice

Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.

recallapplystretch0 of 4 done

Something unclear?

Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.

shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.