Skip to content

Styles and What They Cost

You have requirements that shape structure. This topic is the menu of structures, and the discipline is to describe each one by what it buys and what it costs rather than by how modern it feels.

You already know how these styles work mechanically. What follows is the altitude an architect needs: each style as a position on a small number of quality attributes, so a choice can be argued rather than asserted.

An architectural style is a set of constraints

Section titled “An architectural style is a set of constraints”

A style is a named set of constraints on how a system is divided and how the parts communicate. That is all it is. The constraints are what create the properties — you do not get independent deployability because you called something a microservice; you get it because you accepted the constraint that modules may not share a database or a process.

This matters for the way the choice is made. You are not picking a technology; you are picking which constraints you are willing to live under. Teams that adopt a style without adopting its constraints get the costs and none of the benefits, which is the most common architectural failure in the wild.

The difference shows up most clearly in where a boundary is enforced.

One deployable — boundaries are enforced by the compiler and by review:

graph LR
  A["Module A"] --- B["Module B"]
  B --- C["Module C"]
  A --- C
  subgraph P["One process, one deploy"]
    A
    B
    C
  end

  classDef mod fill:#5B8FB9,stroke:#4A7A9E,stroke-width:2px,color:#ffffff
  class A,B,C mod

Many deployables — the same boundaries are enforced by the network, which never forgets:

graph LR
  D["Service A"] -->|"network"| E["Service B"]
  E -->|"network"| F["Service C"]
  D -->|"network"| F

  classDef svc fill:#D9695B,stroke:#B4483A,stroke-width:2px,color:#ffffff
  class D,E,F svc

The same three-part division, enforced two ways. The second is stronger and strictly more expensive — every line is now a thing that can fail, be slow, or be versioned wrongly.

Style What it buys What it costs
Monolith Simplest possible operations, transactional consistency for free, one deploy, one place to look Change becomes risky as it grows; no independent scaling; one team’s mistake is everyone’s outage
Modular monolith Most of the above, plus enforced internal boundaries that make later extraction cheap Boundary discipline has to be maintained by people, and it erodes the moment a deadline arrives
Microservices Independent deployability, independent scaling, team autonomy, blast-radius containment Every in-process call becomes a distributed one — latency, partial failure, versioning, and an operational burden that needs real platform investment
Event-driven Temporal decoupling, natural fan-out, resilience to downstream slowness, auditability Reasoning about flow becomes genuinely hard, debugging spans systems, and eventual consistency becomes a product question rather than a technical one
Serverless Elastic scale and cost proportional to use, minimal operational floor Cold starts, execution limits, provider coupling, and cost behaviour that becomes unpredictable at high steady volume

Two structural observations about this table.

None of the rows is a winner. If one were, there would be no decision to make and no need for an architect in the conversation.

Styles compose. A real estate of any age is a monolith plus some services plus some event flows, and the useful question is rarely “which style is this system?” but “which style governs this new part, and how does it meet the rest?”

The modular monolith is systematically under-chosen, because it is the only row on the table with no social reward attached to it. It is the right answer more often than the industry’s output of conference talks would suggest, particularly for a new component whose correct boundaries nobody knows yet.

Its specific value is optionality: strong internal boundaries, no distributed-systems tax, and a cheap extraction path later if a boundary turns out to be load-bearing. You pay for that option with discipline, and the discipline is real — the boundaries hold only while someone enforces them.

The honest counter-argument: if the organisation cannot maintain module boundaries inside one codebase, it will not maintain service boundaries either. It will just have the same tangle with network calls in the middle, which is strictly worse. That reasoning is drawn from Ford and Richards’ treatment in Software Architecture: The Hard Parts, and it is worth sitting with before any decomposition.

What drives the choice — and what does not

Section titled “What drives the choice — and what does not”

Three things legitimately drive it: the quality attributes you wrote down in Module 2, the constraints that bound them, and the organisation that has to operate the result.

Three things frequently drive it and should not: familiarity, the desire to have learned something new, and the architecture of a company whose problems are nothing like yours.

The test for whether a choice is real: name the quality attribute that made you reject the simpler option. If you cannot, the simpler option is still the answer.

This topic feeds the style selection with its trade-off table. The rubric requires at least one rejected option with real reasoning — pick the one that was genuinely tempting, not a straw man, and name the ASR that killed it.


→ The table says what each style costs. It does not say how to tell which one a given system needs — that comes from two properties. — Coupling and cohesion