Skip to content
/ Michaël Hompus

Chapter 6 describes runtime behavior: how building blocks collaborate in the scenarios that matter, including alternatives, exceptions, and the bits that tend to hurt in production. It is also the last chapter in the "How is it built and how does it work" group. In this article I show what belongs in chapter 6, what to keep out, a flexible structure you can copy, plus a small example from Pitstop.

This post is about chapter 6: Runtime view, the last chapter in the “How is it built and how does it work” group.

Chapter 5 gave us the map (building blocks and responsibilities). Chapter 6 shows how that map is used in real life: who talks to whom, in what order, and why.

The arc42 template keeps this chapter intentionally “empty” by default. It is basically a container for scenarios: one subchapter per runtime process you want to document.

Note

Chapter 6 can grow a lot. That is not a smell.
If users and external neighbors interact with your system, those flows are architecture.

What belongs in chapter 6 (and what does not)

Chapter 6 of an arc42 document answers:

How does the system behave at runtime in the scenarios that matter?

What belongs here:

  • All relevant runtime scenarios where there is meaningful interaction:
    • user interactions that change state or trigger workflows
    • integrations with external neighbors (inbound/outbound)
    • operationally important processes (batch runs, scheduled jobs, import/export)
    • flows that embody key quality goals (latency, availability, auditability, resilience)
  • For each scenario: the collaboration between the building blocks (names consistent with chapter 5).
  • Alternatives and exceptions where they exist: timeouts, retries, idempotency, partial failures, degraded/offline behavior, manual fallbacks.
  • Notes that help people reason about runtime behavior: correlation IDs, observability points, ordering guarantees, consistency expectations.

Tip

If a neighbor appears in the context view (chapter 3), try to let it show up in at least one runtime scenario over time.
If it never appears, that is useful feedback: maybe it is not a real neighbor, maybe it is background data, or maybe the relevant scenario is still missing.
Either way, treat it as a prompt to revisit the context view in your next iteration.

What does not belong here:

  • Long descriptions of static responsibilities and decomposition. This chapter is about collaboration over time, not “what exists”.
  • A full contract catalog or protocol reference. Link to specs where they live; keep this chapter focused on behavior and responsibilities.
  • Environment-specific deployment details. The runtime behavior should still make sense even if you deploy differently.
  • Low-value diagram noise: repeating “return payload” on every arrow when nothing is transformed, or expanding every internal hop when it adds no architectural insight.
  • Cross-cutting flows that are the same everywhere, such as the OAuth/OIDC login flow. That belongs in chapter 8 as a reusable concept (unless you are literally building an auth service 😅).

Note

Runtime view is where architecture stops being a set of boxes and becomes a set of promises: “this happens”, “this must not happen”, “this is how we recover”.

Diagrams (and how to keep them readable)

Sequence diagrams for sequential flows

Sequence diagrams are excellent at showing who talks to whom, in what order, and why it matters.

Focus on what changes to keep diagrams readable:

  • Request/response pairs
    Show them only when data transforms or meaning shifts. Skip the “return OK” arrows that just echo back what was sent.
  • Internal hops
    Compress them when a layer simply passes data through without adding architectural insight. Three layers calling each other with identical payloads? Show it as one arrow across the boundary.
  • Scenario intent
    Lead with it, not implementation noise. Readers should grasp the essential flow in seconds, then dive into details if they need them.

Example trade-off

A “create order” scenario does not need you to diagram every internal service call. Show the user action, the boundary entry point, the database write, and the response back. Skip the middleware, logging, and validation layers unless they embody a quality goal or failure path.

BPMN for more complex flows

When scenarios have a lot of branching (alt/if/else), loops, delays, sequence diagrams can become a spaghetti scroll. 🍝

That is where BPMN often shines: it stays readable as complexity grows. Camunda Modeler is my go-to tool.

Trade-off: BPMN is typically stored as XML, which is not fun to review in a repo. So exporting diagrams as images becomes an extra step. Just keep the source file and the exported image together.

Tip

You do not need to pick one diagram type for everything. Consistency helps, but clarity helps more.

The minimum viable version

If you are short on time, aim for this:

  1. Start with 1–3 scenarios that cross boundaries: user → system and system → neighbor.
    The first user flow, the first integration, and the first “what if it fails?” path.
  2. For each scenario, add:
    • the intention (what we are trying to achieve)
    • the main participants (aligned with chapter 5)
    • the happy path
    • the first important exception (retry/fallback/manual procedure)
  3. Keep the scenario sections small. Grow later.

Copy/paste structure (Markdown skeleton)

Use this as a starting point. Keep it flexible.

06-runtime-view.md
## 6. Runtime view
<If you have a lot of scenarios, add a table of contents here with links to each scenario.>
### 6.n <Scenario name>
<Write a short intro for the scenario. A few lines is enough: what happens, why it matters, and what "done" looks like.>
_Optional prompts you can include (pick what helps):_
- _Intention:_ what are we trying to achieve?
- _Trigger:_ what starts this (user action, event, schedule)?
- _Participants:_ which building blocks and neighbors are involved?
- _Notes:_ assumptions, alternatives, open topics, relevant links (e.g., ADRs, specs, concepts)
```plantuml
@startuml
title Scenario: <name>
autonumber
actor "User/External" as Actor
participant "UI/Client" as UI
participant "Backend" as Backend
participant "Integration/Adapter" as Integration
database "DB" as DB
Actor -> UI : action
UI -> Backend : request
Backend -> DB : read/write
Backend -> Integration : call out / publish
Integration --> Backend : ack/response
Backend --> UI : result
@enduml
```
**Exceptions and alternatives (optional):**
- <timeout><behavior/fallback>
- <partial failure><behavior/fallback>
- <manual recovery step><who does what>

Tip

If your chapter becomes large (and it might), group scenarios by theme or functionality: “User flows”, “Integrations”, “Operational jobs”, etc.

Example (Pitstop)

Pitstop is my small demo system for this series. It is intentionally simple, so the documentation stays shareable.

6.1 Scenario: Create/update order on appointment import

Why this scenario matters

  • It hits the core value: planning ↔ execution sync.
  • It exercises consistency, auditability, and integration boundaries.
Runtime view

Failure / exception notes

  • Planning API unavailable → Sync queues outbound updates with retry + backoff.
  • Duplicate appointment updates → idempotency key (appointmentId + version/timestamp).
  • Conflicting edits → “last-write-wins” only for safe fields; status changes may require rules (e.g., foreman override).

To browse the full Pitstop arc42 sample, see my GitHub Gist.

Common mistakes I see (and made myself)

  1. Only documenting the happy path
    Architecture shows up in failure handling, retries, timeouts, and recovery.

  2. Diagrams that don’t match your building blocks
    If names and boundaries differ from chapter 5, readers lose their mental model.

  3. Diagram noise instead of insight
    Do not waste pixels on repetitive returns and unchanged payloads.
    Compress internal hops when they add no architectural value.

    User → API → Service → Repository → DB → Repository → Service → API → User
    User → API → Domain write (DB) → API → User
  4. Avoiding “big” because it might become big
    Documenting 27 scenarios is not wrong.
    It becomes wrong when nobody can find anything.
    Group them, index them, or split into linked documents when the system is large.

  5. No external stakeholder recognition
    If a neighbor/system owner cannot recognize their part in the flow, you probably did not document it clearly enough.

Done-when checklist

🔲 Relevant user and neighbor interactions are covered (or explicitly postponed).
🔲 Scenario diagrams use building block names consistent with chapter 5.
🔲 Key alternatives/exceptions are documented where they matter.
🔲 The chapter is navigable: scenarios are grouped and titled clearly.
🔲 Readers can explain “what happens when…” without guessing.

Next improvements backlog

  • Add scenarios for remaining neighbors until the context view is “explained by runtime”.
  • Add idempotency/retry rules for integrations that can duplicate messages.
  • Add observability notes per scenario (correlation IDs, key logs/metrics).
  • Split scenarios into separate linked arc42 documents if the system warrants it.

Wrap-up

Chapter 6 is where your architecture becomes visible in motion. With chapters 4, 5, and 6, the full “How is it built and how does it work” group is complete.

Next up is the “Rules, decisions, and qualities” group starting with arc42 chapter 7 “Deployment view”, where we map building blocks onto infrastructure and environments.

/ Michaël Hompus

Chapter 5 turns strategy into structure using white-box decomposition. It describes the static building blocks of your system, their responsibilities, and the most important dependencies, without diving into runtime flows. Learn what belongs in chapter 5, what to keep out, and get a copy/paste template plus a real example from Pitstop.

This post is about chapter 5: Building block view, the second chapter in the “How is it built and how does it work” group.

Chapter 4 set direction; chapter 5 makes it tangible. Here you describe the static structure of the system: the building blocks, what each one is responsible for, and which dependencies matter.

The goal is not to document everything. The goal is to give readers a mental map of the solution, so changes and discussions stop happening “in someone’s head”.

Note

This post is longer because chapter 5 introduces hierarchical decomposition (a.k.a. zooming in step by step): start small, and only add detail when it prevents real misunderstandings.

What belongs in chapter 5 (and what does not)

The main job of chapter 5 of an arc42 document is to answer:

What are the main parts of the system, and what is each part responsible for?

What belongs here:

  • A building block hierarchy (level 1–3), from coarse to detailed.
  • Per building block:
    • responsibility (one sentence)
    • key dependencies
    • main interfaces (what it offers/needs)
  • The boundaries that matter: ownership, responsibilities, and “who is allowed to change what”. When multiple teams work on the same system, building block boundaries often align with team ownership. If changing a block requires coordination with another team, that boundary is worth documenting.
  • The structural consequences of your strategy from chapter 4 (e.g., modular monolith vs distributed, having a BFF, etc.).
  • Links to source code or generated docs when that helps (if building blocks map to modules/packages/repos).

What does not belong here:

  • Copy/pasting large parts of earlier chapters.
    Refer back to the goals, constraints, and context when you need them, but keep this chapter focused on responsibilities and boundaries.
  • Step-by-step flows, sequencing, or “and then it calls X” stories.
    This chapter is about static structure, not behavior.
  • Environment-specific deployment and infrastructure details.
    Keep those concerns separate so the building block view stays stable even when environments change.
  • Full interface specifications and contract catalogs.
    You can link to OpenAPI/AsyncAPI or other specs, but avoid duplicating payloads and edge cases here.
  • Low-level implementation decisions that change frequently.
    If it is likely to flip during sprints (a library choice, an internal pattern tweak), it does not belong in the core structure.

The “white-box” metaphor

The core concept of this chapter is the black-box vs. white-box approach.

  • Chapter 3 was the black-box view: The system is a sealed opaque block. We only described what crosses the boundary (interfaces) and who sits outside (neighbors), but internals were invisible (hence “black” or opaque).
  • Chapter 5 is the white-box series: We “open the lid” of the system. We look inside to see how it is constructed.

Level 1 opens the main black box. If a component inside Level 1 is complex, we treat that component as a black box first, then open it up in Level 2 (its white-box view). This hierarchical decomposition is standard in arc42 and aligns with the C4 Model “Zoom” concept.

Levels mean different things in different documents

First, a blunt disclaimer: The building block levels are a zoom tool, not a fixed taxonomy. You stop decomposing when you can no longer explain why the detail matters to your architectural goals.

What “level 1–3” means depends on what you are documenting:

  • For a large system, level 1 might be products, level 2 domains/services, and level 3 microservices.
  • For a single (micro)service, level 1 might be the service boundary, level 2 internal modules, and level 3 namespaces.
  • For a platform/library team, level 2 might describe public APIs or even classes, because that is what stakeholders integrate with, and level 3 might be implementation details that only the owning-team needs to understand.

Tip

Pick the level of detail that matches your stakeholders. A diagram is successful when it answers their questions, not when it contains more boxes.

Level 1 should match chapter 3

Level 1 is where you show the system boundary and the neighbors. It should include the same external neighbors you introduced in chapter 3.

Warning

Do not confuse context with building blocks.

  • Chapter 3: Who/what is outside, and what crosses the boundary?
  • Chapter 5 Level 1: What are the main internal building blocks, and how do they depend on each other and their connection to the external neighbors?

That creates a nice “thread” through the document:

  • chapter 3: who we interact with
  • chapter 5: how we are structured to deal with that
  • chapter 6: how the collaboration plays out at runtime (spoiler alert! 🫣)

Do not repeat interface details on every level

Interfaces show up on multiple levels, but you do not have to repeat everything. Repeating payloads and contracts at every zoom level creates noise and maintenance debt.

A practical rule:

  • Level 1: Name the interactions (e.g., “Appointments”, “Status Updates”) so the relationship is clear.
  • Level 2/3: Document the interface where the contract lives (e.g., in the integration module or port) and link to the source/spec.

When you are describing interfaces on a level, it could be helpful to separate them into:

  • external interfaces (tie back to chapter 3)
  • internal interfaces (boundaries between your own building blocks, e.g. a frontend-backend API or a module’s public API)

The minimum viable version

If you are short on time, aim for this:

  1. One level 1 diagram showing the system boundary and all relevant neighbors from chapter 3.
  2. A short table describing each level-1 building block: responsibility + key dependencies.
  3. Optionally: one level 2 zoom for the one area that is complex or risky.

Then stop. 🛑

Copy/paste structure (Markdown skeleton)

Use this as a starting point and keep it small.

05-building-block-view.md
## 5. Building block view
### 5.1 Level 1: White-box overall system
<Short explanation: what are the major building blocks and why this decomposition?>
```plantuml
@startuml
title Level 1 - Building block view (placeholder)
skinparam componentStyle rectangle
actor "User role" as User
[External System A] as ExtA
[External System B] as ExtB
[Identity Provider] as IdP
package "Our System" {
[UI / Clients] as UI
[Application Core] as Core
[Integration Adapters] as Adapters
[Realtime Updates] as Realtime
[Persistence] as Persistence
}
User --> UI
UI --> Core
Core --> Persistence : store state / history
Core --> Realtime : publish updates
Core --> Adapters : integration ports
Core --> IdP : auth (optional)
Adapters --> ExtA
Adapters --> ExtB
@enduml
```
<How to read this diagram:
boxes = responsibilities/ownership,
arrows = dependencies (not runtime sequence),
labels = intent (not necessarily protocol).>
#### Building blocks (level 1)
| Building block | Responsibility | Depends on | Notes |
| :------------- | :------------- | :--------- | :---- |
| ... | ... | ... | ... |
#### External interfaces (optional)
| Peer | Interface | Direction | Protocol/Format | Where documented |
| :--- | :-------- | :-------- | :-------------- | :--------------- |
| ... | ... | ... | ... | chapter 3 / spec |
#### Internal interfaces (optional)
| Between | Interface | Purpose | Notes |
| :------ | :-------- | :------ | :---- |
| ... | ... | ... | ... |
### 5.2 Level 2: <Building block> (only where it matters)
<Zoom into one block that is risky/complex. Keep it a white-box view.>
```plantuml
@startuml
title Level 2 - <Building block> (placeholder)
package "<Building block>" {
[Module A] as A
[Module B] as B
[Module C] as C
}
A --> B
B --> C
@enduml
```
### 5.3 Level 3: <Optional deeper zoom>
<Only when your stakeholders need it: namespaces, packages, public APIs, or even classes.
For example, if a level-2 module has a complex internal structure that other teams integrate with,
zooming in to show its public API surface and internal layering can prevent misunderstandings.>
<Consider linking to source code / generated docs when available.>

Tip

If building blocks map cleanly to code, link them. Some teams generate docs straight from source (Doxygen-style or similar), which can make this chapter accurate and cheap to maintain.

Example (Pitstop)

Pitstop is my small demo system for this series. It is intentionally simple, so the documentation stays shareable.

This is what chapter 5 looks like when filled in.

5. Building block view

5.1 White-box overall system

Level 1 - Building block view

Building blocks (level 1)

BlockResponsibilityKey Interfaces
Admin Overview UIDashboard, coordination, customer comms supportHTTPS/JSON to Backend
Workshop View UIBay/task board, fast updates, degraded modeWebSocket/JSON to Backend
BackendCore domain + APIs + orchestrationHTTPS/JSON + WS + internal module interfaces
Sync & IntegrationMapping + sync strategy per planning vendorREST/JSON, webhooks, retry
Audit/Event LogImmutable history for accountability + analyticsAppend/read APIs
DBOperational persistenceSQL (implementation-specific)

5.2 Level 2 — Pitstop Backend

Level 2 - Pitstop Backend

Notes

  • Modules contain domain rules.
    The Integration Ports (a ports-and-adapters pattern, as chosen in chapter 4) isolate vendor protocols and mapping, so domain modules do not depend on external systems directly.
  • Reporting read models can be optimized independently (avoid OLTP pain).

Building blocks (level 2)

ElementResponsibilityDepends on
Work Order ModuleCore logic for ordersCustomer, Audit
Workshop ModuleMechanic task managementWorkOrders, Audit
Admin ModuleConfiguration & overridesAudit
Customer/Vehicle ModuleShared entity dataAudit
ReportingRead-optimized views(Domain Events)
Planning PortAdapter for Planning ServiceExternal
Notification PortAdapter for Notification ServiceExternal
Audit WriterCentralized compliance loggingDB
API LayerProtocol handling (HTTP/WS)Auth, Modules

To browse the full Pitstop arc42 sample, see my GitHub Gist.

Note

A level 3 zoom into the Work Order Module could show its internal structure (e.g., command handlers, domain entities, validation rules) if stakeholders need that detail. For brevity, we leave it out here.

Common mistakes I see (and made myself)

  1. Too much detail too early
    If chapter 5 looks like a class diagram, it will not be maintained. Start coarse, and zoom in only where complexity justifies it.

  2. Building blocks without responsibilities
    Boxes called Service and Manager are not responsibilities. Each block should say what it owns: persistence, state transitions, messaging, integrations, etc.

  3. Mismatch with chapter 3
    If chapter 3 lists neighbors, level 1 should show them. As you document the white-box, you might find a specific module that talks to an external system you forgot to list in chapter 3. Consistency goes both ways!

  4. Repeating interface specs everywhere
    Do not duplicate protocol and payload details on every level. Put the detail where it makes sense (often chapter 3) and link to it.

  5. Forgetting “source of truth”
    For important data: who owns it, and who is allowed to change it? If you do not answer this, production will answer it for you.

  6. Using technology names as architecture
    Kafka and PostgreSQL are implementation choices. Building blocks should describe responsibilities (message bus, persistence, state, integrations), so your diagrams remain useful when technology or deployment changes.

Done-when checklist

🔲 Level 1 includes the system boundary and the neighbors from chapter 3.
🔲 Each building block has a clear responsibility in one sentence.
🔲 External interfaces are referenced (and not duplicated) where documented.
🔲 Level 2/3 are used only when complexity or stakeholders require it.
🔲 A new team member can explain “what lives where” after reading this chapter.

Next improvements backlog

  • Add ADR links when boundaries or decomposition are disputed (chapter 9).
  • Add level 3 only for a few areas where deeper detail prevents misunderstandings.
  • Add links to code/docs where building blocks map cleanly to modules or repos.

Wrap-up

Chapter 5 is the map. 🗺️
It helps people find responsibilities, boundaries, and where to implement changes.

Next up: arc42 chapter 6, “Runtime view”, where we put this structure in motion and describe the most important end-to-end flows.

/ Michaël Hompus

Chapter 4 opens the "How is it built and how does it work" group. It is where goals, constraints, and context from the first three chapters start to shape the design through a small set of guiding decisions. In this article I show what belongs in chapter 4, what to keep out, how to handle open strategy questions, and a flexible structure you can copy, plus a small example from Pitstop.

This post opens the “How is it built and how does it work” group.

The first three chapters can feel like silos: each one introduces its own set of information. Here, those inputs start to shape the design. This is where you set direction for the solution.

Your solution strategy should fit the goals from chapter 1, operate within the non-negotiables from chapter 2, and respect the boundaries and partners from chapter 3.

Early in a project this chapter can be short. That is normal. The strategy grows as you learn, as constraints become concrete, and as decisions are made.

What belongs in chapter 4 (and what does not)

Chapter 4 of an arc42 document answers one question:

What is our approach, and which major decisions guide the design?

What belongs here:

  • A short list of guiding choices that shape the whole design. For each choice a short rationale: why this direction fits the goals, constraints, and context.
  • The “heavy” decisions that should not change every sprint:
    Major platform choices, integration strategy, monolith vs distributed, data approach, deployment style.
  • Trade-offs and rationale, linked back to earlier chapters where possible.
  • Consequences (direction and impact), so people understand what follows from the strategy.
  • Links to ADRs when they exist (chapter 9).

If your list grows over time, group the strategy items into a few buckets that fit your scope (pick what matches your system), for example:

  • Structure (e.g., monolith/modular/distributed, boundaries, layering)
  • Integrations (e.g., ports/adapters, sync model, contract strategy)
  • Data (e.g., ownership, consistency model, auditability approach)
  • Operations (e.g., deployment style, runtime isolation, observability)

What does not belong here:

  • Detailed breakdowns of internal parts and their dependencies.
  • Step-by-step interaction flows or scenario descriptions.
  • Environment-specific operational details.
  • Small, sprint-level technical choices that are likely to change often.
  • Copy/pasting earlier chapters: link to the drivers instead and focus on what you decided and what it implies.

Note

Strategy is not the same as “technology list”.
A good strategy explains why a direction makes sense and what it implies.

This chapter often starts almost empty

Early in the design process, chapter 4 can be short. That is normal.

As the design and build progresses, this chapter becomes the place where everything starts to connect: quality goals, constraints, concepts, deployment choices, and runtime behavior.

If a strategy item is negotiable, keep it lightweight. If it is truly a “heavy” direction setter, make sure it is backed by a constraint, a discussion, or an ADR.

Tip

Chapter 4 is also a good place to list open strategy questions that still need a decision. A visible list of unknowns is more useful than pretending everything is decided.

The minimum viable version

If you are short on time, aim for a small set of strategy statements as concise bullets with just enough context to steer design.

A good “minimum viable” strategy statement usually contains:

  • Approach / decision (one line)
  • Rationale (one or two short lines: why this direction)
  • Consequence / impact (one short line: what this enables or constrains)
  • Traceability to one or more inputs:
    • driver(s) from chapter 1
    • constraint(s) from chapter 2
    • context/partner boundary from chapter 3

You do not need to hit an exact number of lines, you can combine them in a readable way. The key is that the rationale and impact are clear and concise, and that it is easy to see how the choice connects back to the drivers.

Copy/paste structure (Markdown skeleton)

Use this as a starting point and keep it small.

04-solution-strategy.md
## 4. Solution strategy
<1–3 short paragraphs: what is the overall approach and why?>
<Use whatever format keeps it readable: prose, sub-bullets, or a table.
Each item should make the rationale, impact, and link to a driver clear.>
- **<Strategy / decision name>**
<Why this direction, what it enables or constrains,
and which goal/constraint/context item it traces back to.>
- **<Strategy / decision name>**
...
### Open strategy questions (optional)
- **Question:** ...
Why it matters: ...
Next step / owner: ...

Note

Strategy statements should be short.
If you need a full page to explain one item, you probably want to split details into another chapter and link to it.

Tip

Where you put open questions depends on how you work.
If your process is strategy-driven (pick direction first, then refine), keeping them in chapter 4 works well.
If your process is more risk-driven (track uncertainties and mitigation first), you might prefer chapter 11 and link to them from here.

Example (Pitstop)

Pitstop is my small demo system for this series. It is intentionally simple, so the documentation stays shareable.

This is what chapter 4 looks like when filled in.

4. Solution strategy

Pitstop is designed as an operational source of truth for work orders and status, with near real-time synchronization between planning and workshop execution.

  • Modular monolith backend (initially)
    Keep deployment simple and change-friendly while the domain stabilizes. Modules are strict (no “grab-bag services”) and communicate via explicit interfaces.
  • Adapter-based integrations (Planning, Notifications, Parts status)
    Each external system sits behind a port/adapter boundary to protect domain logic and keep new integrations fast. Traces to: Modifiability goal (≤ 2 days), Planning integration constraint.
  • Near real-time updates via push
    Workshop and admin need shared truth quickly (≤ 2 seconds). Use WebSocket/SSE where possible; fall back to efficient polling. Traces to: Consistency goal, near real-time constraint.
  • Degraded-mode workshop operation
    Workshop UI supports local queueing and later sync when connectivity returns. Traces to: Resilience goal, degraded-mode constraint.
  • Audit-first changes for work order state
    Every status change and important edits record who/when/why (immutable history), enabling dispute resolution and throughput analysis.

Open strategy questions

  • Question: WebSocket vs SSE as the default push channel?
    Affects real-time UX and infra constraints. Validate with UI needs + ops constraints.
  • Question: What conflict resolution approach do we use after offline edits?
    Affects user trust and operational continuity. Define business rules with workshop stakeholders.

To browse the full Pitstop arc42 sample, see my GitHub Gist.

Common mistakes I see (and made myself)

  1. No strategy statements
    If chapter 4 is empty or just a placeholder, the architecture lacks direction. Without strategy, designs drift and teams lose alignment.

  2. Repeating the earlier chapters instead of linking
    Chapter 4 should build on chapters 1, 2, and 3, not copy them. Use links and focus on the consequences.

  3. Only listing technologies
    We use Kubernetes is not a strategy.
    We deploy as containers because ops standardizes on it is.

  4. No rationale
    Without rationale, strategy statements look like preferences.
    Tie each item back to a goal, constraint, or context boundary.

  5. Treating consequences as a negative
    Consequences are direction.
    If a choice does not enable anything valuable for stakeholders, it is a smell.

  6. Making it too detailed
    Chapter 4 should be readable in a few minutes.
    Details belong in other chapters and ADRs.

  7. Hiding unknowns
    If open questions only live in someone’s head, the team cannot contribute.
    Making assumptions explicit invites feedback and prevents silent divergence.

Done-when checklist

🔲 Contains a small set of strategy statements (not a tech wishlist).
🔲 Each statement has a short rationale and a clear impact.
🔲 Statements link back to goals/constraints/context (chapters 1, 2, 3).
🔲 The choices feel stable enough to not change every sprint.
🔲 Open strategy questions are visible (here or in chapter 11), not hidden in someone’s head.

Next improvements backlog

  • Review strategy statements with ops and key external stakeholders for realism.
  • Add links to ADRs as decisions become concrete (chapter 9).
  • Add a short mapping from strategy to top quality goals.
  • Move unstable or controversial topics into “Open strategy questions” until decided.
  • Remove strategies that no longer serve stakeholder value (and document the change as an ADR).

Wrap-up

Chapter 4 is where the design starts to take shape. It should be short, directional, and connected to the drivers you already captured in the first 3 chapters.

Next up: arc42 chapter 5, “Building block view”, where we describe the solution structure without diving into runtime sequencing yet.

/ Michaël Hompus

Chapter 3 draws the boundary of your system. If it is unclear what is inside and outside, integrations and expectations will break first. In this article I show what belongs in chapter 3, what to keep out, and a minimal structure you can copy, plus a small example from Pitstop.

Chapter 3 is the last chapter in the “Why and where” group. It is where you draw the line between your system and the outside world.

If that line is unclear, failures show up eventually: unclear responsibilities, failing integrations, and mismatched expectations.

This chapter is split into two views:

  • Business context: who interacts with the system, and what value or information is exchanged.
  • Technical context: what interfaces exist, and how integration actually happens.

What belongs in chapter 3 (and what does not)

Chapter 3 of an arc42 document answers one question:

What is inside our system, what is outside, and how do we interact?

What belongs here:

  • A clear inside vs outside boundary.
  • External business actors and neighboring systems with responsibilities.
  • The direction of exchanges (who initiates, who responds).
  • Examples of value or data exchanged (not only APIs: files, emails, manual exports, spreadsheets, SFTP drops).
  • The most important interfaces (APIs, messaging, files, UI hand-offs, SSO, batch jobs).
  • Links to existing interface documentation (OpenAPI/AsyncAPI/specs) if it exists.

What does not belong here:

  • Internal building blocks and components (chapter 5).
  • Runtime scenarios and sequencing (chapter 6).
  • Deployment layouts (chapter 7).
  • Technical design details that do not cross the boundary.

Note

If there is no separate API documentation, chapter 3 is the place to document your interfaces. Even when you can link to OpenAPI or AsyncAPI documents, include 1–2 small sample payloads here.
It makes the integration real and readable without forcing people to open a separate spec.

Diagrams: modeling tool or text-based

Diagrams make chapter 3 click. You can draw them in a modeling tool like Sparx Enterprise Architect, but you can also keep them close to the code using text-based diagrams.

I prefer PlantUML component diagrams for this chapter, because the system boundary and interfaces are easy to read.

Text-based diagrams work well because they are easy to diff, review, and version together with the documentation.

Tip

Use whatever keeps the diagram maintained.
A perfect diagram that nobody updates is less useful than a simple one that stays correct.

The minimum viable version

If you are short on time, aim for this:

  1. One business context diagram (or a table) listing the key actors/systems and what they exchange.
  2. One technical context diagram (or a table) listing the top interfaces with direction and protocol.
  3. For the top 1–3 interfaces: add a short example (sample payload, file format snippet, or message shape).

That is enough to prevent most boundary and integration surprises.

When this chapter becomes high value

As soon as you have quality goals around availability, latency, or operational continuity, your interfaces need a bit more than we call API X.

For your top interfaces, add:

  • SLA/SLO expectations and support windows
  • Failure behavior and fallback procedures
  • Retry/idempotency rules
  • Rate limits and quotas
  • Security and trust boundaries

This is often where the conversation moves from it depends to concrete trade-offs.

Copy/paste structure (Markdown skeleton)

Use this as a starting point and keep it small.

03-context-and-scope.md
## 3. Context and scope
### 3.1 Business context
<Who is outside the system, what value/data is exchanged?>
```plantuml
@startuml
title Business context (placeholder)
actor "External Actor" as Actor
component "Neighboring System" as Neighbor
component "Our System" as OurSystem
Actor -> OurSystem : value / info
OurSystem --> Neighbor : value / info
Neighbor --> OurSystem : value / info
@enduml
```
| External actor / system | Responsibility | Exchange with our system |
| :---------------------- | :------------- | :----------------------- |
| ... | ... | ... |
### 3.2 Technical context
<Which technical interfaces exist, and how do we integrate?>
```plantuml
@startuml
title Technical context (placeholder)
component "External System" as External
component "Identity Provider" as IdP
component "Our System" as OurSystem
External <--> OurSystem : HTTP + JSON
OurSystem --> IdP : OIDC/OAuth2
@enduml
```
| Peer | Interface | Owner | Direction | Protocol / format | Notes |
| :--- | :-------- | :---- | :-------- | :---------------- | :---- |
| ... | ... | ... | ... | ... | ... |
#### 3.2.1 Interface: <name>
**Purpose:** <why does this interface exist?>
**Direction:** <A -> B, source of truth?>
**Link to spec:** <OpenAPI/AsyncAPI link if it exists>
**Examples (recommended):**
<Description>
```json
{ "example": "payload" }
```
**Expectations and exceptions (optional):**
| SLA/SLO | Failure behavior | Retry / idempotency | Fallback / manual procedure |
| :------ | :--------------- | :------------------ | :-------------------------- |
| ... | ... | ... | ... |

Example (Pitstop)

Pitstop is my small demo system for this series. It is intentionally simple, so the documentation stays shareable.

This is what chapter 3 looks like when filled in.

3. Context and scope

3.1 Business context

Pitstop sits between planning and the workshop. It keeps work orders and status in sync so people stop copying information between tools.

Business context
Actor/SystemResponsibilityExchanges with Pitstop
CustomerBrings car, receives updatesETA updates (via advisor/portal)
Service AdvisorManages appointment & expectationsPriority changes, notes, customer communication
Workshop ForemanOrchestrates executionAssignments, reprioritization
MechanicPerforms workStatus updates, findings, time spent
Planning ServiceOwns schedule/time slotsAppointment import, reschedule suggestions
Notification Service (optional)Contact customersSMS/email updates

3.2 Technical context

Technical context
PeerInterfaceOwnerDirectionProtocol/FormatNotes
Planning ServiceAppointments APIPlanning vendorInboundREST/JSONFull import + incremental sync
Planning Service (optional)WebhooksPlanning vendorInboundHTTP/JSONPush appointment changes
Planning ServiceStatus updatesPitstop teamOutboundREST/JSONDelay, ready, reschedule proposal
Admin Overview UIWork Orders APIPitstop teamBidirectionalHTTPS/JSONRBAC, dashboards
Workshop View UILive UpdatesPitstop teamBidirectionalWebSocket/JSONLow latency, optimized payloads
Notification Service (optional)Notifications APIPitstop teamOutboundREST/JSONCustomer updates

3.2.1 Interface: Appointments API

3.2.1.1 Examples

Appointment imported from planning:

{
"appointmentId": "A-10293",
"plate": "12-AB-34",
"start": "2026-01-12T09:00:00+01:00",
"service": "OilChange",
"customerRef": "C-4451"
}

3.2.2 Interface: Work Orders API

3.2.2.1 Examples

Workshop update from a mechanic:

{
"workOrderId": "WO-7781",
"status": "WaitingForParts",
"note": "Brake pads not in stock",
"updatedBy": "mechanic-17",
"updatedAt": "2026-01-12T10:41:00+01:00"
}

To browse the full Pitstop arc42 sample, see my GitHub Gist.

Note

Interfaces are not always APIs.
Manual exports, emailed files, spreadsheets, SFTP drops, and someone retypes it are also integrations.
If information crosses the boundary, document it here.

Common mistakes I see (and made myself)

  1. Only naming neighbors, without exchanges
    A box called CRM is not useful by itself. Document what is exchanged and why.

  2. Mixing business and technical context
    Business context is about responsibilities and value. Technical context is about protocols and integration mechanics. Mixing them makes both harder to read.

  3. Treating REST as the only interface
    REST is common, but not universal. File transfers, messaging, batch jobs, manual steps and spreadsheets all matter.

  4. No ownership
    If you do not document who owns an external interface, you will not know who to call when it breaks.

  5. No direction
    We integrate with X is vague. Who initiates, who is the source of truth, who is allowed to change state?

  6. No examples
    Even when you have OpenAPI or AsyncAPI, one small payload example prevents a lot of misunderstandings.

  7. No expectations for critical interfaces
    If availability or latency matters, document assumptions: SLAs, failure behavior, retry rules, and fallback procedures.

Note

If an external stakeholder cannot recognize their responsibilities and expectations in this chapter, the integration is not documented clearly enough yet.

Done-when checklist

🔲 The system boundary is clear (inside vs outside).
🔲 Business actors and neighboring systems are listed with responsibilities.
🔲 The top interfaces are listed with direction, protocol/format, and owner.
🔲 The most important integrations have 1–3 small examples (payload, file snippet, message shape).
🔲 Critical interfaces have expectations (SLA/failure behavior) or are explicitly marked as unknown.

Next improvements backlog

  • Add links to OpenAPI/AsyncAPI documents (or create them if missing).
  • Add SLA/SLO and failure behavior for the top 3 interfaces.
  • Add a short note about trust boundaries and data classification (if relevant).
  • Add examples for non-API integrations (file drop, manual export, batch job) if they exist.
  • Review chapter 3 with external stakeholders (planning vendor/team, ops, security) for recognition and correctness.

Wrap-up

Chapter 3 is where you make expectations explicit. Most problems show up at the boundary first, so investing in this chapter pays off quickly.

This concludes the “Why and where” group of arc42 chapters. Next, we move on to the “How is it built and how does it work” group.

Next up: arc42 chapter 4, “Solution strategy”, where we describe the approach and major decisions that guide the design.

/ Michaël Hompus

Chapter 2 lists the non-negotiables that shape your design space. If you do not write these down early, they will still exist, but they will surprise you later. In this article I show what belongs in chapter 2, what to keep out, and a minimal structure you can copy, plus a small example from Pitstop.

Chapter 2 is part of the “Why and where” group. It is the chapter where you write down the rules you cannot break.

This is not about what you prefer. It is about what your organization, environment, or stakeholders already decided for you.

If you do not document constraints early, they still shape the architecture. You just discover them at the worst possible time.

Constraints also have a positive side: there are thousands of ways to build the same functionality. A short list of non-negotiables helps you narrow down options early, before you invest in the wrong direction.

I have seen teams pick a public cloud technology because it fit the solution, while the product had to run air-gapped on-premises. Or because it was “hot” (call it: conference-driven design), while operations would only support a single platform. Money got wasted before someone finally said: this was never negotiable.

What belongs in chapter 2 (and what does not)

Chapter 2 of an arc42 document answers one question:

What limits our freedom, no matter what solution we pick?

What belongs here:

  • Organizational constraints (budget/time, team skills, governance, contracting).
  • Technical constraints (platforms/stack, operations model, security/compliance rules).
  • Integration constraints (what you must connect to, formats you must accept).
  • Conventions (coding standards, CI/CD rules, naming/versioning, documentation rules).
  • References to standards you must follow.

What does not belong here:

  • Architecture choices you still get to make (save those for chapter 4 and chapter 9).
  • Personal preferences (I like microservices, we always use Kafka).
  • Detailed design, diagrams, protocols, or deployment layouts.

Note

A constraint is a rule you must follow.
A decision is a choice you make.
If you mix them, chapter 2 becomes a debate instead of a boundary.

Constraints exist on multiple levels

Organizations often have architecture and constraints at multiple levels (enterprise, domain, platform, product, application). You can use arc42 at all those levels, but in practice most teams start at the bottom: an application or service.

That is also where chapter 2 becomes very practical: many constraints already exist as company policies and standards.

Tip

Link to existing policies instead of rewriting them.
They tend to be stable, owned, and updated in one place.
Your chapter 2 should explain the impact, not duplicate the policy text.

Many policies ultimately follow from a company mission and vision. So even if a constraint looks “technical”, it often exists for a business reason. Writing down the rationale helps prevent this is stupid discussions later.

The minimum viable version

If you are short on time, aim for this:

  • 8–15 constraints in a table
  • each constraint includes:
    • a clear statement
    • a type (organizational, technical, convention, integration, compliance)
    • a short rationale
    • the impact on design
    • a reference or owner (where it came from)

That is enough to prevent surprise constraints late and to make later decisions faster.

Copy/paste structure (Markdown skeleton)

Use this as a starting point.

02-architecture-constraints.md
## 2. Architecture constraints
Non-negotiables that shape the design space.
| Constraint | Type | Rationale | Impact on design | Reference |
| :--------- | :------------- | :-------- | :--------------- | :-------- |
| ... | Organizational | ... | ... | ... |
| ... | Technical | ... | ... | ... |
| ... | Convention | ... | ... | ... |
Notes:
- If a constraint has exceptions, describe the exception path.
- Link to standards, policies, or owners as references.

Note

A table is not mandatory.
If your constraints list grows, grouping them by type (e.g., organizational, technical, conventions, compliance) can be more readable.
The key is still the same: statement, rationale, impact, and source.

Example (Pitstop)

Pitstop is my small demo system for this series. It is intentionally simple, so the documentation stays shareable.

This is what chapter 2 looks like when filled in.

2. Architecture constraints

Non-negotiables that shape the design space:

ConstraintTypeRationaleImpact on design
Must integrate with Planning Service(s)IntegrationExisting ecosystem realityAPI contracts, sync strategy, mapping rules
Near real-time UI updatesUX/OperationalWorkshop coordinationPush updates (WebSocket/SSE) or efficient polling
Degraded-mode operationOperationalGarage networks can be unreliableLocal cache/queue, retry, conflict handling
Containerized deploymentPlatformStandard ops modelRegistry, base images, runtime policy
Automated CI + testsProcessFast feedback and reliabilityPipeline ownership + test environments
GDPR / minimal personal dataComplianceCustomer dataData minimization, retention rules, audit controls
Deviations recorded as ADRsGovernancePrevent silent divergenceADR workflow and traceability (chapter 9)

To browse the full Pitstop arc42 sample, see my GitHub Gist.

Common mistakes I see (and made myself)

  1. Writing constraints too late
    If chapter 2 is empty, people will assume freedom that does not exist. Then the first real constraint shows up during implementation, procurement, or security review.

  2. Using vague words
    Secure, fast, cloud-ready are not constraints.
    Write constraints as rules you can test against: must run on-prem, must be air-gapped, must use SSO.

  3. Mixing constraints and decisions
    We will use PostgreSQL is usually a decision.
    We must use the company-managed PostgreSQL platform is a constraint.
    If it is not truly non-negotiable, move it to chapter 4 or chapter 9.

  4. No impact column
    A constraint without impact does not help the team. The value is in translating a rule into a design consequence.

  5. Forgetting conventions and governance
    Conventions feel boring until they break delivery: CI/CD rules, versioning, naming, documentation rules, ADR requirements. Put them here so they are explicit.

Exceptions and experiments

Non-negotiable does not mean “never”. Sometimes you run an experiment to learn, or you need an exception for a specific case.

Tip

When you make an exception, document it as an ADR and link it here.
The goal is not bureaucracy.
The goal is that the next team does not rediscover the same debate.

Done-when checklist

🔲 Chapter 2 contains the real non-negotiables, not preferences.
🔲 Each constraint has a clear impact on design and delivery.
🔲 Each constraint has a source (owner, standard, policy, or link).
🔲 The list is short enough to scan, but complete enough to prevent surprises.

Next improvements backlog

  • Review the list with ops, security, and the product owner (fast reality check).
  • Add links to central standards (security baseline, platform rules, CI/CD guidance).
  • Mark constraints that are assumptions and confirm them (or remove them).
  • Add ADR links for any local deviations from central architecture/platform rules.
  • Split the table into sub-sections if it grows (organizational, technical, conventions).

Wrap-up

Chapter 2 is where you protect your future self. Constraints narrow the solution space, so later decisions become faster and more consistent.

Next up: arc42 chapter 3, “Context and scope”, where we draw the boundary and make integrations and expectations explicit.