Published: Last updated:

System Architecture

Boundaries Decide More Than the Framework

Architecture is not a one-off choice but a sequence of trade-off decisions along competing quality attributes. The pragmatic path leads from a strictly modularised modulith step by step to services, only where the forces demand it. Modularisation beats the initial framework choice.

A faulty decision in early phases generates technical debt whose costs rise disproportionately in later growth phases. The lever against this is not the "right" framework but clean boundaries, documented decisions (Architecture Decision Records, ADRs), and the freedom to swap individual building blocks later. What this discipline looks like as a running operation is the focus of our Platform Engineering and Internal Developer Platform competency.

The Forces: Competing Quality Attributes Drive the Architecture

Architecture is the optimisation against competing quality attributes. No attribute is free, strengthening one weakens another. These forces, not fashion, drive every good decision:

  • Scalability: Do parts of the system need to bear load independently? A rarely used reporting feature scales differently from a checkout under peak load.
  • Maintainability: How quickly does a new team member understand an area and change it safely? This is tied directly to the sharpness of module boundaries.
  • Time-to-market: How fast does a team ship a feature without blocking others?
  • Team topology: How many teams work on the system, and how autonomous must they be? That is the subject of Conway's Law.
  • Operational maturity: Can the organisation handle distributed systems? Observability, deployment automation, and on-call are the prerequisite, not the consequence.
  • Data consistency: Does the case need strong consistency (one transaction) or is eventual consistency enough? This question decides service cuts more than any other.
  • Sovereignty: Do the building blocks stay swappable and self-hostable? See replaceability as a quality attribute below.

Whoever fails to name these forces still decides, just unconsciously. The sections below make the trade-offs visible.

The Building Blocks and Their Boundaries

An architecture consists of building blocks (modules, services) and the boundaries between them. The central insight: boundaries arise from the domain, not from technology. A cut along domain boundaries (Bounded Contexts from Domain-Driven Design) stays stable; a cut along technical layers (frontend, backend, database) only produces distributed coupling.

The API is the contract: if building blocks communicate exclusively via defined interfaces, the inside stays swappable. This contract discipline sits at the heart of API-First. Whether a block runs as a module in the same process or as its own service is a question of deployment, not of the cut. The domain boundary is independent of it.

The diagram below shows the pragmatic default as a single picture: a modulith with strict internal boundaries from which one context is already extracted as a service. Monolith, modulith, and services are not an either/or here but a continuum.

architecture-beta
    group edge(cloud)["Access"]
    group core(server)["Modulith"]
    group legacy(server)["Replacement"]
    service client(cloud)["Client"] in edge
    service gateway(server)["API Gateway"] in edge
    service catalog(server)["Catalog module"] in core
    service customers(server)["Customer module"] in core
    service orders(server)["Order module"] in core
    service invoice(server)["Invoice service"] in legacy
    service erp(database)["Legacy ERP"] in legacy
    client:R -- L:gateway
    gateway:R -- L:catalog
    catalog:R -- L:customers
    customers:R -- L:orders
    gateway:B -- T:invoice
    invoice:R -- L:erp

The diagram reads like this: The modulith stays the default; one forced cut (invoicing) is extracted as its own service and, via the Strangler Fig mechanism, gradually replaces the legacy ERP. The API gateway is the only communication boundary to the outside. It is not a big-bang microservices picture, but a targeted cut along the forces.

The Spectrum: from monolith through modulith to services

"Monolith or microservices?" is the wrong question. There is a spectrum, and each step optimises different attributes. The choice is a trade-off, not a creed:

  • Development speed (small)
    • Monolith: high
    • Modulith (default): high
    • Microservices: low (overhead)
  • Operational complexity
    • Monolith: low
    • Modulith (default): low
    • Microservices: high (distributed)
  • Scaling granularity
    • Monolith: coarse (all)
    • Modulith (default): coarse (all)
    • Microservices: fine (per service)
  • Team autonomy
    • Monolith: low
    • Modulith (default): medium
    • Microservices: high
  • Latency / consistency
    • Monolith: simple (local)
    • Modulith (default): simple (local)
    • Microservices: hard (network, eventual)
  • Operational maturity required
    • Monolith: low
    • Modulith (default): low
    • Microservices: high

The modulith, a monolith with strictly enforced internal module boundaries, is the pragmatic default for most Swiss SMEs: operated as simply as a monolith, but with clean cuts that allow later extraction. The dangerous middle stage is the distributed monolith: services in name only, yet so tightly coupled that they can only be deployed together. That yields the operational complexity of Microservices without the autonomy gain. (Compare Microservices for the spectrum's end and MACH architecture for one concrete point on it.)

Failure Modes

Architecture rarely fails for lack of knowledge but from predictable patterns:

  • Big Ball of Mud: the unstructured monolith in which every change triggers unpredictable side effects. The team spends more time fixing bugs than building features.
  • Distributed monolith: microservices without real decoupling, deployable only together, a shared database, synchronous call chains. Worse than a monolith because it is distributed.
  • Premature decomposition: cutting services before the domain boundaries are understood. Wrong cuts are far more expensive to correct in a distributed system than in a modulith.
  • Shared database as hidden coupling: two services, one database. The interface is secretly the schema, not the API. Every migration couples both teams. (See Data Architecture.)
  • Missing operational maturity: microservices without Observability and Platform Engineering shift complexity into operations, where nobody sees it until it burns.

Four of these five failure modes result from a too early or too poor service cut, which leads directly to the evolution path.

The Evolution Path

Architecture evolves. The robust path starts simple and cuts only under proven pressure, asking do the forces force a cut? The gate in the diagram is the central discipline: without a forcing force, the modulith stays.

graph TB
    A["Monolith"] --> B["Modulith:<br/>strict boundaries"]
    B --> G{"Do the forces<br/>force a cut?"}
    G -->|"no"| B
    G -->|"yes"| C["Strangler Fig<br/>extraction"]
    C --> D["API-first<br/>decoupling"]
    D --> E["ADRs as<br/>memory"]
    E --> G

The diagram reads like this: From the monolith to the modulith with clean boundaries, then a decision gate. Only when a concrete force (differing scaling, team autonomy, technology constraint) forces the cut is a single context extracted via Strangler Fig, decoupled API-first, and the decision recorded as an ADR. The loop back to the gate makes it clear: every further cut runs through the same check. Clean module boundaries emerge continuously through Refactoring, and the diagram vocabulary (Context, Container, Component) comes from the C4 model. Whether a cut is genuinely ready is what our Service Delivery Assessment checks neutrally.

Whoever proceeds this way need not "rebuild" an architecture "in 5 years". It stays replaceable because the boundaries are clean and the decisions documented. Modularisation matters more than the initial framework choice.

Architecture and Team: Conway's Law

Conway's Law states that organisations produce systems that mirror their communication structure. Three teams that barely talk to each other produce three barely integrated subsystems, regardless of the architecture diagram on the wall. The inverse, the Inverse Conway Maneuver, turns this into a tool: first define the target architecture, then cut the teams to match. Whoever wants checkout and catalogue as separate services needs separate, autonomous teams. The Team Topologies framework (Skelton/Pais) formalises this in four team types (stream-aligned, platform, enabling, complicated subsystem). Deep dive in the Conway's Law topic.

Replaceability as an Architecture Quality Attribute

An architecture of swappable, self-hostable building blocks with open interfaces keeps control over data and operations in-house and keeps the system adaptable. This sovereignty is not a compliance checkbox but an architecture quality attribute, and it is won or lost at design time. This is exactly where the API-as-contract discipline pays off twice: whoever encapsulates their building blocks behind clear interfaces can swap a proprietary service for an open alternative without rebuilding the system. Avoiding Vendor Lock-in is therefore an architecture decision, not a later procurement trick, and the core of the digital sovereignty that le dot champions as a positioning for Swiss companies. The business context for the Strangler Fig path is usually Legacy Modernisation.

Related topics

References

Ask AI

These links open external AI services, the conversation and its content are sent to their providers.