Lesson 2 of 4
Structure Serves Quality Attributes
Structure is never the goal. It is the mechanism by which a system achieves the qualities someone is willing to pay for — and those qualities are always in conflict.
Functional requirements tell you what a system does. They almost never determine its architecture. Two systems that do exactly the same thing — accept an order, charge a card, ship a parcel — can have completely different architectures, because they are held to completely different standards of availability, latency, and rate of change.
The attributes that actually drive decisions
| Attribute | Vague version | Usable version |
|---|---|---|
| Availability | The system should be reliable | 99.95% monthly for the checkout path, measured at the load balancer |
| Latency | Pages should load fast | Search returns in under 300ms at p99 with 500 concurrent users |
| Scalability | It should scale | Handles 10x current write volume without a schema change |
| Modifiability | The code should be maintainable | A new payment provider ships in under two weeks by one team |
| Security | It must be secure | No component can read another tenant's rows even if its own code is compromised |
| Observability | We need good logging | Any production request can be traced end to end within five minutes |
Every attribute is bought with another
This is the part that separates architecture from wishful thinking. Quality attributes are not a checklist to maximise; they are a budget to allocate. Improving one almost always degrades another, and an architect who cannot name what a decision cost has not finished thinking.
- Availability is usually bought with consistency — replicas that keep serving during a partition are replicas that can serve stale data.
- Latency is usually bought with freshness, via caching, or with cost, via more capacity held idle.
- Modifiability is usually bought with indirection, and indirection is bought with the cognitive cost of tracing a call through four layers.
- Security is usually bought with convenience — every isolation boundary is also a boundary developers have to work across.
- Independent deployability is bought with operational complexity: more pipelines, more runtimes, more failure modes to understand.
Quality attributes drive structure
The same functional requirement produces two different architectures depending on the attributes it must satisfy.
A flow from left to right. Business goals feed into quality attribute requirements, which drive architectural decisions, which produce the resulting structure. Feedback from measured behaviour returns to the quality attribute requirements.
Business goal
Enter a new market
Revenue driver
Reduce support cost
Margin driver
Quality attributes
Data residency in EU
Regulatory
99.95% checkout uptime
Measured at LB
New provider in 2 weeks
Modifiability
Decisions
Region-partitioned data
Provider behind a port
Async order fulfilment
Structure
Regional deployments
Adapter per provider
Outbox + queue
In practice
Two order systems, opposite architectures
Two teams build an order-processing system. Functionally they are near-identical: accept an order, reserve stock, charge a card, notify the warehouse. One is for a regional furniture retailer processing 400 orders a day. One is for a flash-sale marketplace processing 40,000 orders in the ninety seconds after a drop.
Constraints
- Identical functional requirements
- Retailer: 400 orders/day, 5 engineers
- Marketplace: 40,000 orders in 90 seconds, 40 engineers
- Both need correct inventory
Decision
The retailer built a modular monolith with synchronous, transactional order processing against one PostgreSQL instance. The marketplace built queue-based intake with optimistic stock reservation, an event-driven fulfilment pipeline and eventual consistency between reservation and payment.
Why
The retailer's dominant attribute is modifiability with five engineers, and a transaction gives them correctness for free. The marketplace's dominant attribute is surviving a 500x load spike, which no synchronous transaction against a single database can absorb; they trade immediate consistency for the ability to accept the burst at all.
What it cost
The marketplace pays for it permanently: they now have to handle oversold stock with compensation logic, they need idempotent consumers, and a new engineer takes six weeks rather than six days to become productive. That is the correct trade for them and would be a catastrophic one for the retailer — the same design is right in one context and wrong in the other.
A stakeholder tells you the new reporting system "needs to be highly available and always show the latest data". What is your next move?RevealHide
Point out, without being smug about it, that they have asked for both sides of a trade-off and that you need to know which one wins when a network partition happens. Then get specific: what is the actual availability target, how stale is too stale, and what does the business lose in each case? Very often the honest answer is "reports can be five minutes behind but must never be down", which resolves the design instantly. The skill is not knowing CAP — it is converting a contradictory sentence into a decidable question.
Key takeaways
- Functional requirements rarely determine architecture; quality attributes do.
- A quality attribute without a number and a measurement point cannot be designed for or tested.
- Attributes are traded, never maximised — naming what a decision cost is part of making it.
- Two systems with identical features can correctly have opposite architectures.
- Designing for attributes nobody asked for is as damaging as ignoring the ones they did.