skip to content

How do you pick an architectural style (layered, hexagonal, event-driven, microkernel, CQRS, space-based, microservices) from quality-attribute drivers rather than from fashion?

level: middleimportance: must knowfreq 72%

answer

  1. Rank top 3 -ilities, not all
  2. Every style sells something
  3. Scalability ≠ elasticity
  4. Simplest style that satisfies drivers
  5. ADR + fitness function to hold the line

basics

~20 s

Start from the two or three qualities that matter most — say, deployability and fault isolation, or simplicity and cost — rank them, and pick the style that scores highest on those while accepting its known weaknesses. Every style trades some qualities away; none wins everywhere.

solid answer

~60 s

Selection is a ranking exercise, not a search for the best style. Steps: (1) gather the drivers — functional shape (is the domain variable? read-heavy? bursty?), constraints (team size, budget, compliance, latency budget), and the quality attributes that would make the system a failure if missed; (2) rank the top three, because a style that maximizes everything does not exist; (3) map drivers to styles using their known profiles — layered for simplicity and low cost, hexagonal for testability and technology independence, event-driven for elasticity and responsiveness under bursty load, microkernel for domain variability and third-party extension, CQRS for asymmetric read/write load or models, space-based for extreme concurrent user spikes without a database bottleneck, microservices for independent deployability and fault isolation across many teams; (4) explicitly name what you are giving up; (5) record it in an ADR and, where possible, encode the constraint as an automated fitness function so it does not erode. Default to the simplest style that meets the ranked drivers — usually a modular monolith — and keep the seams that allow a later split.

go deeper

for a junior

Say that different styles suit different needs, and give one concrete pair — layered for a small simple app, microservices when many teams must deploy independently.

for a middle

Show the process: gather drivers, rank the top three, map to candidate styles, and name what each style sacrifices. Mention that the simplest adequate style is the default.

for a senior

Turn drivers into measurable scenarios, compare two or three candidates on the ranked attributes, propose hybrids at the smallest effective scope, and cover ADRs plus automated fitness functions.

for a principal

Add the organizational dimension (Conway's law, team topologies), the economics of reversibility and optionality, how drivers are elicited from stakeholders who all say 'everything is critical', and how you set explicit re-evaluation triggers.

### The vocabulary you need first **Quality attribute** (also non-functional requirement, or *-ility*): a measurable property of *how* the system behaves rather than *what* it does — availability, scalability, elasticity, performance (latency/throughput), testability, deployability, modifiability/evolvability, fault tolerance, security, simplicity, and overall cost. "Fast" is useless; **"p99 checkout latency under 300 ms at 5,000 requests/second"** is a driver you can architect against. **Architectural driver**: the subset of requirements and constraints that actually shape structure. Three sources: - *Quality-attribute requirements* — the ranked -ilities above. - *Constraints* — non-negotiable givens: team of four, must run on-prem, data must stay in-region, must integrate with a 20-year-old mainframe. - *Functional shape* — the parts of the domain that create structural pressure: heavily variable business rules, wildly asymmetric read vs write volume, unavoidable long-running workflows, unpredictable traffic spikes. **Scalability vs elasticity** — a distinction people blur. Scalability is handling growth in total load over time; elasticity is absorbing sudden bursts (ticket on-sale, flash sale) within seconds. They select different styles: scalability may be satisfied by adding instances behind a load balancer; extreme elasticity is what pushes people to space-based or event-driven designs. ### The catalog with its driver profile | Style | Buys you | Costs you | Reach for it when | |---|---|---|---| | **Layered (n-tier)** | simplicity, low cost, easy hiring, fast start | poor deployability (whole app redeploys), weak scalability granularity, slow change as it grows | small team, modest load, domain not yet understood, cost dominates | | **Hexagonal / ports & adapters** | testability, technology independence, delayed infrastructure commitment | more indirection, mapping code, harder for juniors to navigate | the domain is the valuable part; you expect to swap delivery mechanisms or datastores | | **Modular monolith** | simplicity plus enforced internal boundaries; a cheap path to later splitting | still one deployment unit and one failure domain | most systems, most of the time — the sane default | | **Event-driven** | elasticity, responsiveness, decoupling of producers from consumers, natural async workflows | eventual consistency, hard debugging/tracing, error handling and ordering complexity | bursty load, many reactions to one fact, workflows that need not be synchronous | | **Microkernel (plugin)** | extensibility for highly variable rules, third-party or per-customer customization | plugin contract/versioning burden, registry and isolation complexity | tax rules per jurisdiction, insurance product variants, an IDE-style product | | **CQRS** | independent scaling/optimizing of reads and writes, simpler models on each side | two models to keep in sync, usually eventual consistency, more moving parts | reads vastly outnumber writes, or the read shape genuinely differs from the write shape | | **Space-based** | extreme elastic concurrency by removing the central database from the hot path | in-memory data grid complexity, cache/replication semantics, data-loss risk windows | huge unpredictable concurrent-user spikes where the DB is the proven bottleneck | | **Microservices** | independent deployability, fault isolation, per-service scaling, team autonomy | network latency and partial failure, distributed data and transactions, heavy ops/platform investment | many teams needing to ship independently, sharply different scaling or availability needs per capability | ### A workable selection procedure 1. **Elicit and rank drivers.** Force a ranked top three. If everyone says "all of them are critical", make them choose what they'd sacrifice first — the answer is what the architecture will actually optimize. 2. **Turn each into a scenario with numbers.** "When a marketing email goes out, traffic rises 40× within two minutes and must be served with p95 under 500 ms." Now elasticity is measurable and you can tell whether a style plausibly delivers it. 3. **Score the candidate styles** on those top drivers only, and note what each sacrifices. Two or three candidates is plenty. 4. **Consider hybrids.** The winning answer is often "modular monolith, hexagonal inside, with an event-driven edge for notifications, and CQRS only in the reporting context". Apply expensive styles at the *smallest scope that solves the problem*. 5. **Prefer the simplest option that satisfies the ranked drivers.** Complexity has a permanent operational cost; simplicity is itself a quality attribute (often the one that decides whether the team can still ship in year three). 6. **Write an ADR** — context, ranked drivers, options, decision, consequences accepted. 7. **Protect the decision with fitness functions** — automated checks in CI that enforce the constraint (no module may import another's internals; no service may open a connection to another service's database; a build fails if a layer is skipped). Without these, styles decay into big balls of mud within a year. ### Common failure modes - **Resume-driven / conference-driven selection.** Choosing microservices for a four-person team buys distributed-systems failure modes and pays for none of the benefits, because the benefit — independent deployment by independent teams — does not exist yet. - **Optimizing for an unranked attribute.** Building for a scale you will not see for five years while missing the time-to-market driver that determines whether the company survives to see it. - **Ignoring constraints.** A brilliant event-driven design is worthless if the operations team cannot run a broker or the compliance regime forbids the data movement. - **Treating the choice as permanent.** Drivers change (10 users → 10 million; one team → twelve). Re-evaluate at intervals, and prefer decisions that keep seams visible so migration is a refactor rather than a rewrite. - **Ignoring Conway's law.** Systems mirror the communication structure of the organization that builds them. A style that conflicts with the org chart will either be violated or force a reorg; decide which consciously. ### How to answer in an interview Refuse to name a favorite style. Ask for drivers, rank them, name two candidate styles with their explicit trade, state what you'd sacrifice, and mention how you would keep the decision enforced (fitness functions) and revisitable (ADRs, seams).

  • Your product owner ranks 'time to market' first and 'scale to a million users' second. Which style do you propose?
    A modular monolith, likely hexagonal inside, deployed as one unit. It maximizes delivery speed now while the module boundaries and any async edges preserve the option to extract the hot capability into a service later. I'd add a concrete trigger for re-evaluation — for example, when two teams start blocking each other on releases.
  • How do you stop a chosen style from eroding over the next two years?
    Encode its constraints as automated fitness functions in CI — dependency-direction checks, module-boundary tests, a check that no service connects to another's schema, latency budgets asserted in performance tests. Reviews alone do not survive turnover; a failing build does.
  • Which quality attribute do teams most often forget to rank, and why does it matter?
    Simplicity, and closely related, operability. They rarely appear on a requirements list yet they determine whether the team can still change the system in year three; complexity accrues interest continuously and is very hard to pay down.

Choosing a vehicle: nobody asks "what is the best vehicle?" You ask what you're hauling, how far, on what roads, and with what budget. A van, a motorbike, and a truck each win decisively under different constraints — and 'fastest' plus 'cheapest' plus 'carries a ton' is not on the menu.

context