Deliverables

The curriculum covers what an architect should know. This covers what an architect actually hands over: 55 artifacts, each with a worked example, a note on when it is worth producing, who reads it, and the ways it usually goes wrong. Filter by the artifact's type, the kind of engagement that calls for it, the stack or industry it is drawn against, or the audience it is written for.

Identify the deliverable → 42 diagrams, shown one at a time with the answer withheld. Nothing to submit.

29 of 55 deliverables shown.

flowchart LR
  sales["Sales<br/><i>quote, opportunity, discount</i>"]
  orders["Ordering<br/><i>order, line, fulfilment</i>"]
  billing["Billing<br/><i>invoice, credit note, dunning</i>"]
  ship["Shipping<br/><i>consignment, manifest</i>"]
  legacy["Legacy Mainframe<br/><i>account master</i>"]

  sales -->|"Customer / Supplier"| orders
  orders -->|"Customer / Supplier"| billing
  orders -->|"Published Language"| ship
  legacy -->|"Anti-Corruption Layer"| orders
  billing -.->|"Shared Kernel — party identity"| sales
Structural View

Bounded Context Map

The domain model's fault lines — which parts of the business have their own language, and what kind of relationship each pair of them has.

flowchart TB
  gw["HTTP Gateway<br/><i>inbound</i>"]
  subgraph svc["Order API — inside the container"]
    direction TB
    ctrl["Order Controller<br/><i>validation, mapping</i>"]
    app["Order Application Service<br/><i>use cases, transactions</i>"]
    dom["Order Domain Model<br/><i>invariants, state rules</i>"]
    repo["Order Repository<br/><i>persistence port</i>"]
    pay["Payment Client<br/><i>anti-corruption adapter</i>"]
    out["Outbox Publisher"]
  end
  db[("PostgreSQL")]
  ext["Payment Provider"]
  bus[["Kafka"]]

  gw --> ctrl --> app
  app --> dom
  app --> repo --> db
  app --> pay --> ext
  app --> out --> db
  out -.->|"relay reads outbox"| bus
Structural View

Component Diagram

The inside of one runnable unit — its major code-level groupings, their responsibilities and what each one talks to.

C4 Model Design
flowchart TB
  cust(["Customer"])
  subgraph boundary["Order Management"]
    direction TB
    web["Web Application<br/><i>Next.js</i>"]
    api["Order API<br/><i>Java / Spring Boot</i>"]
    worker["Fulfilment Worker<br/><i>Java / Spring Boot</i>"]
    db[("Order Store<br/><i>PostgreSQL</i>")]
    queue[["Order Events<br/><i>Kafka</i>"]]
    cache[("Session Cache<br/><i>Redis</i>")]
  end
  pay["Payment Gateway"]

  cust -->|"HTTPS"| web
  web -->|"JSON over HTTPS"| api
  api -->|"reads and writes"| db
  api -->|"reads and writes"| cache
  api -->|"publishes"| queue
  queue -->|"consumes"| worker
  worker -->|"reads and writes"| db
  worker -->|"HTTPS"| pay
Structural View

Container Diagram

One level inside the system boundary — the separately deployable and runnable pieces, each named with the technology it is built on.

C4 Model Design
flowchart TB
  subgraph l1["Experience"]
    direction LR
    e1["Web"] --- e2["Mobile"] --- e3["Partner Portal"]
  end
  subgraph l2["Channel & API"]
    direction LR
    c1["API Gateway"] --- c2["BFF"] --- c3["Event Ingress"]
  end
  subgraph l3["Business Services"]
    direction LR
    b1["Ordering"] --- b2["Pricing"] --- b3["Fulfilment"] --- b4["Billing"]
  end
  subgraph l4["Integration"]
    direction LR
    i1["Message Broker"] --- i2["Adapters"] --- i3["File Transfer"]
  end
  subgraph l5["Data"]
    direction LR
    d1["Operational Stores"] --- d2["Analytical Platform"] --- d3["Cache"]
  end
  subgraph l6["Infrastructure"]
    direction LR
    f1["Compute"] --- f2["Network"] --- f3["Storage"]
  end
  l1 --> l2 --> l3 --> l4 --> l5 --> l6

  sec["Security<br/>&<br/>Identity"]
  ops["Observability<br/>&<br/>Operations"]
Structural View

Layered Architecture Diagram

The solution as horizontal capability tiers with cross-cutting concerns as vertical bars — the picture executives expect and the one most often drawn without meaning.

flowchart TB
  cust(["Customer"])
  agent(["Support Agent"])
  sys["Order Management<br/>the system being described"]
  pay["Payment Gateway<br/>external SaaS"]
  erp["ERP<br/>existing on-premises"]
  mail["Email Provider<br/>external SaaS"]
  crm["CRM<br/>external SaaS"]

  cust -->|"places and tracks orders"| sys
  agent -->|"amends and refunds orders"| sys
  sys -->|"authorises and captures"| pay
  sys -->|"posts financial documents"| erp
  sys -->|"sends confirmations"| mail
  sys -->|"reads account and entitlement"| crm
Structural View

System Context Diagram

The single box of your system surrounded by the people and external systems it talks to, and nothing about how it is built inside.

Context Diagrams Discovery
flowchart LR
  subgraph cust["Customer"]
    direction TB
    c1(["Submits claim"])
  end
  subgraph intake["Intake — automated"]
    direction TB
    a1["Validate policy"]
    a2{"Policy active<br/>and in cover?"}
    a3["Auto-assess<br/><i>rules + model</i>"]
    a4{"Confidence<br/>&ge; threshold?"}
  end
  subgraph handler["Claims Handler"]
    direction TB
    h1["Manual review"]
    h2{"Approve?"}
  end
  subgraph fin["Finance"]
    direction TB
    p1["Schedule payment"]
  end

  c1 --> a1 --> a2
  a2 -->|"no"| r1(["Reject — notify with reason"])
  a2 -->|"yes"| a3 --> a4
  a4 -->|"yes"| p1
  a4 -->|"no"| h1 --> h2
  h2 -->|"yes"| p1
  h2 -->|"no"| r2(["Decline — notify with appeal route"])
  p1 --> e1(["Paid"])
Behavioural View

BPMN Process Diagram

A business process as tasks in swim lanes with explicit decision points and handoffs, where crossing a lane boundary is the interesting event.

Business Processes Discovery
flowchart LR
  commit(["commit to main"]) --> build

  subgraph ci["Continuous Integration"]
    direction TB
    build["build<br/><i>pinned deps, hermetic</i>"]
    unit["unit tests<br/><i>&lt; 4 min</i>"]
    scan["SAST + dependency<br/>+ secret scan"]
    sign["sign artifact<br/>+ emit SBOM"]
    build --> unit --> scan --> sign
  end

  sign --> reg[("artifact registry<br/><i>immutable, digest-addressed</i>")]

  subgraph cd["Continuous Delivery"]
    direction TB
    dev["deploy dev<br/><i>auto</i>"]
    ctest["contract tests"]
    stage["deploy staging<br/><i>auto</i>"]
    nft["performance +<br/>resilience suite"]
    dev --> ctest --> stage --> nft
  end

  reg --> dev
  nft --> gate{"release gate<br/><i>automated checks +<br/>change record</i>"}
  gate -->|"pass"| canary["canary 5%<br/><i>15 min bake</i>"]
  gate -->|"fail"| stop(["blocked"])
  canary --> analyse{"error rate and<br/>latency within SLO?"}
  analyse -->|"yes"| full["progressive rollout<br/><i>25% → 50% → 100%</i>"]
  analyse -->|"no"| rollback(["automatic rollback"])
Behavioural View

CI/CD Pipeline Diagram

The path from commit to production as ordered stages, showing what each one proves, what it produces, and where a human is still in the loop.

flowchart LR
  subgraph t1[" "]
    direction TB
    c1["cmd: Place Order"]
    e1["OrderPlaced<br/><i>fact</i>"]
    r1[("read: Order Status")]
    c1 --> e1 --> r1
  end
  subgraph t2[" "]
    direction TB
    c2["cmd: Authorise Payment"]
    e2["PaymentAuthorised<br/><i>fact</i>"]
    r2[("read: Payment Ledger")]
    c2 --> e2 --> r2
  end
  subgraph t3[" "]
    direction TB
    c3["policy: on PaymentAuthorised<br/>allocate stock"]
    e3["StockAllocated<br/><i>fact</i>"]
    r3[("read: Availability")]
    c3 --> e3 --> r3
  end
  subgraph t4[" "]
    direction TB
    c4["policy: on StockAllocated<br/>request despatch"]
    e4["ConsignmentCreated<br/><i>fact</i>"]
    r4[("read: Tracking")]
    c4 --> e4 --> r4
  end
  e1 --> c2
  e2 --> c3
  e3 --> c4
Behavioural View

Event Model

The business as a sequence of facts that happened, with the command that caused each and the read models and reactions it feeds.

flowchart TB
  subgraph fwd["Forward path"]
    direction LR
    f1["1. Reserve stock"] --> f2["2. Authorise payment"] --> f3["3. Create consignment"] --> f4["4. Capture payment"] --> f5["5. Despatch"]
  end
  subgraph comp["Compensation"]
    direction RL
    k1["Release stock"] --- k2["Void authorisation"] --- k3["Cancel consignment"] --- k4["Refund<br/><i>visible to customer</i>"]
  end
  f1 -.->|"undo"| k1
  f2 -.->|"undo"| k2
  f3 -.->|"undo"| k3
  f4 -.->|"undo"| k4
  f5 -.->|"no undo — goods have left"| x(["point of no return"])
Behavioural View

Saga Compensation Flow

A multi-service transaction as forward steps each paired with an undo, showing where the sequence becomes irreversible.

sequenceDiagram
  autonumber
  participant C as Client
  participant G as API Gateway
  participant O as Order Service
  participant P as Payment Gateway
  participant Q as Event Log

  C->>G: POST /orders (Idempotency-Key)
  G->>O: create order
  O->>O: persist as PENDING
  O->>P: authorise (deadline 3s)
  alt authorised
    P-->>O: approved + auth id
    O->>O: mark CONFIRMED
    O->>Q: OrderConfirmed
    O-->>G: 201 Created
  else declined
    P-->>O: declined
    O->>O: mark REJECTED
    O-->>G: 402 Payment Required
  else timeout
    P--xO: no response by deadline
    O->>O: keep PENDING
    O-->>G: 202 Accepted (poll for status)
    Note over O,P: reconciliation job settles<br/>PENDING against the provider
  end
  G-->>C: response
Behavioural View

Sequence Diagram

One scenario as an ordered exchange of messages between participants, with time on the vertical axis and the failure paths drawn rather than assumed.

stateDiagram-v2
  [*] --> Pending: order placed
  Pending --> Authorised: payment approved
  Pending --> Rejected: payment declined
  Pending --> Expired: no response in 24h
  Authorised --> Picking: stock allocated
  Authorised --> Cancelled: customer cancels
  Picking --> Shipped: consignment handed to carrier
  Picking --> Backordered: stock unavailable
  Backordered --> Picking: stock replenished
  Backordered --> Cancelled: customer cancels
  Shipped --> Delivered: carrier confirms
  Shipped --> Lost: no scan in 14 days
  Delivered --> Returned: return accepted
  Rejected --> [*]
  Expired --> [*]
  Cancelled --> [*]
  Delivered --> [*]
  Returned --> [*]
  Lost --> [*]
Behavioural View

State Machine Diagram

The legal states of one entity and the events that move it between them, which is where illegal transitions become visible.

flowchart LR
  a["Idea accepted<br/><i>work 2d</i>"]
  w1(["wait 9d<br/>backlog"])
  b["Refinement<br/><i>work 1d</i>"]
  w2(["wait 4d<br/>awaiting design"])
  c["Build<br/><i>work 5d</i>"]
  w3(["wait 3d<br/>awaiting review"])
  d["Code review<br/><i>work 0.5d</i>"]
  w4(["wait 6d<br/>awaiting test env"])
  e["Test<br/><i>work 2d</i>"]
  w5(["wait 11d<br/>awaiting release window"])
  f["Release<br/><i>work 0.5d</i>"]

  a --> w1 --> b --> w2 --> c --> w3 --> d --> w4 --> e --> w5 --> f
  f --> tot["Work 11d &middot; Wait 33d<br/>Lead time 44d &middot; Flow efficiency 25%"]
Behavioural View

Value Stream Map

Every step from request to delivery with its work time and its wait time, exposing that most of the elapsed time is queueing.

Flow Metrics Discovery
flowchart LR
  party["Party"]
  cust["Customer"]
  supp["Supplier"]
  prod["Product"]
  order["Order"]
  ship["Shipment"]
  inv["Invoice"]
  pay["Payment"]
  loc["Location"]

  cust -->|"is a"| party
  supp -->|"is a"| party
  cust -->|"places"| order
  order -->|"is for"| prod
  supp -->|"supplies"| prod
  order -->|"is fulfilled by"| ship
  ship -->|"is sent to"| loc
  order -->|"is billed on"| inv
  inv -->|"is settled by"| pay
Data View

Conceptual Data Model

The twelve or so things the business talks about and how they relate, with no attributes, no keys and no technology.

Data Architecture Discovery
erDiagram
  CUSTOMER ||--o{ ORDER : places
  CUSTOMER ||--o{ ADDRESS : has
  ORDER ||--|{ ORDER_LINE : contains
  ORDER }o--|| ADDRESS : "ships to"
  ORDER ||--o| PAYMENT : "settled by"
  PRODUCT ||--o{ ORDER_LINE : "appears in"
  PRODUCT }o--|| CATEGORY : "belongs to"

  CUSTOMER {
    uuid id PK
    string email UK
    string status
    timestamp created_at
  }
  ORDER {
    uuid id PK
    uuid customer_id FK
    uuid ship_to_id FK
    string status
    numeric total_minor
    string currency
  }
  ORDER_LINE {
    uuid id PK
    uuid order_id FK
    uuid product_id FK
    int quantity
    numeric unit_price_minor
  }
  PAYMENT {
    uuid id PK
    uuid order_id FK
    string provider_ref UK
    string state
  }
Data View

Entity Relationship Diagram

Entities, their attributes and the cardinality between them — where the notation on the end of each line is the actual content.

flowchart TB
  users(["Users"]) --> dns["Global DNS<br/><i>latency routing + health checks</i>"]

  subgraph r1["Region: primary"]
    direction TB
    lb1["Load Balancer<br/><i>public</i>"]
    subgraph az1["Zone A"]
      n1["Node Pool<br/><i>api ×3, worker ×2</i>"]
    end
    subgraph az2["Zone B"]
      n2["Node Pool<br/><i>api ×3, worker ×2</i>"]
    end
    subgraph az3["Zone C"]
      n3["Node Pool<br/><i>api ×2, worker ×1</i>"]
    end
    db1[("Primary DB<br/><i>synchronous replica in Zone B</i>")]
    lb1 --> n1
    lb1 --> n2
    lb1 --> n3
    n1 --> db1
    n2 --> db1
    n3 --> db1
  end

  subgraph r2["Region: secondary"]
    direction TB
    lb2["Load Balancer<br/><i>warm</i>"]
    n4["Node Pool<br/><i>api ×2, scaled down</i>"]
    db2[("Read Replica<br/><i>asynchronous — RPO 30s</i>")]
    lb2 --> n4 --> db2
  end

  dns --> lb1
  dns -.->|"failover only"| lb2
  db1 -.->|"async replication"| db2
Deployment & Infrastructure View

Deployment Diagram

Which runtime artifact runs on which infrastructure, in which zone and region, and what fails when one of those boundaries fails.

flowchart LR
  subgraph e1["Ephemeral / PR"]
    direction TB
    a1["scaled to 1<br/>mocked externals<br/>synthetic data<br/><i>proves: it builds and unit-passes</i><br/>auto-destroy 24h"]
  end
  subgraph e2["Dev"]
    direction TB
    a2["shared<br/>real internal deps<br/>synthetic data<br/><i>proves: integration wiring</i><br/>anyone deploys"]
  end
  subgraph e3["Staging"]
    direction TB
    a3["prod-shaped topology<br/>real deps · sandbox externals<br/>masked prod-like data<br/><i>proves: contracts + performance</i><br/>pipeline only"]
  end
  subgraph e4["Production"]
    direction TB
    a4["full scale · multi-AZ<br/>real data<br/><i>proves: nothing — it serves</i><br/>pipeline + gate"]
  end
  e1 --> e2 --> e3 --> e4
  note["Same artifact promoted throughout.<br/>Config differs; the image digest does not."]
Deployment & Infrastructure View

Environment Topology

Which environments exist, what each one proves, what data it holds and who may deploy to it.

flowchart TB
  subgraph prod["Cluster: prod-eu (regional, 3 AZ)"]
    direction TB
    cp["Control plane<br/><i>managed · private endpoint</i>"]
    subgraph pools["Node pools"]
      direction LR
      np1["system<br/><i>taint: CriticalAddonsOnly</i>"]
      np2["general<br/><i>3–30 nodes · spot 40%</i>"]
      np3["memory<br/><i>taint: workload=memory</i>"]
      np4["gpu<br/><i>taint: workload=gpu</i>"]
    end
    subgraph ns["Namespaces"]
      direction LR
      n1["team-orders<br/><i>quota · NetworkPolicy<br/>default-deny</i>"]
      n2["team-pricing<br/><i>quota · NetworkPolicy</i>"]
      n3["platform<br/><i>mesh · ingress · logging</i>"]
    end
    cp --- pools
    pools --- ns
  end
  subgraph nonprod["Cluster: nonprod-eu"]
    direction TB
    x1["shared node pool<br/><i>spot 90%</i>"]
  end
  reg[("Image registry<br/><i>signed images only</i>")] --> prod
  reg --> nonprod
  gitops["GitOps reconciler"] -.->|"applies desired state"| prod
Deployment & Infrastructure View

Kubernetes Cluster Topology

How many clusters, split by what, which node pools exist and what isolates one tenant from another.

sequenceDiagram
  autonumber
  participant B as Browser
  participant A as App / BFF
  participant I as Identity Provider
  participant R as Resource API

  B->>A: GET /protected
  A-->>B: 302 to IdP (PKCE challenge, state, nonce)
  B->>I: authorise request
  I->>B: authenticate + MFA
  I-->>B: 302 back with authorisation code
  B->>A: code + state
  Note over A,I: back channel — browser never sees these
  A->>I: exchange code + PKCE verifier + client secret
  I-->>A: access token (10 min), refresh token, id token
  A->>A: store tokens server-side<br/>set HttpOnly SameSite cookie
  A-->>B: session cookie only
  B->>A: subsequent request + cookie
  A->>R: call with access token (Bearer)
  R->>I: fetch/refresh signing keys (JWKS, cached)
  R->>R: verify signature, issuer, audience,<br/>expiry, scope
  R-->>A: 200
  A-->>B: rendered response
  Note over A,I: on expiry the BFF refreshes<br/>with rotating refresh token
Security View

Authentication Flow Diagram

The exact token exchange between browser, application, authorisation server and API — including what is short-lived, what is bound and what never touches the browser.

flowchart LR
  user(["Customer<br/><i>untrusted</i>"])
  admin(["Admin<br/><i>privileged</i>"])

  subgraph edge["Boundary 1 — public edge"]
    cdn["CDN / WAF"]
  end

  subgraph app["Boundary 2 — application tier"]
    direction TB
    api["Order API"]
    auth["Auth Service"]
  end

  subgraph datab["Boundary 3 — data tier"]
    direction TB
    db[("Order Store<br/><i>PII + card token</i>")]
    kms[("Key Vault")]
  end

  ext["Payment Provider<br/><i>third party</i>"]

  user -->|"F1 HTTPS"| cdn
  cdn -->|"F2 HTTPS + mTLS"| api
  admin -->|"F3 admin console"| api
  api -->|"F4 token introspection"| auth
  api -->|"F5 TLS + parameterised"| db
  api -->|"F6 fetch DEK"| kms
  api -->|"F7 HTTPS outbound"| ext
  ext -->|"F8 webhook — signed"| cdn
Security View

Threat Model Data Flow Diagram

Processes, stores and flows with trust boundaries drawn across them, so that every boundary crossing can be enumerated for threats.

flowchart TB
  s(["Alert: order submit p99 > 900 ms<br/>for 5 min"])
  s --> c1["1. Confirm scope<br/><i>one region or global?</i>"]
  c1 --> q1{"Global?"}
  q1 -->|"no"| a1["2a. Check that region's<br/>dependency health"]
  q1 -->|"yes"| a2["2b. Check shared dependencies:<br/>DB, cache, identity"]
  a1 --> q2{"Region-local cause?"}
  q2 -->|"yes"| m1["3. Shift traffic away<br/><i>runbook OPS-04</i>"]
  q2 -->|"no"| a2
  a2 --> q3{"DB CPU > 80%<br/>or replication lag > 10s?"}
  q3 -->|"yes"| m2["4. Enable read-path cache bypass=off<br/>+ raise connection limit<br/><i>flag: cache.aggressive</i>"]
  q3 -->|"no"| q4{"Recent deploy<br/>in last 60 min?"}
  q4 -->|"yes"| m3["5. Roll back<br/><i>runbook OPS-01</i>"]
  q4 -->|"no"| esc(["6. Escalate to<br/>Order team on-call<br/><i>stop investigating</i>"])
  m1 --> v["7. Verify p99 recovers<br/>within 10 min"]
  m2 --> v
  m3 --> v
  v --> q5{"Recovered?"}
  q5 -->|"yes"| done(["Close · record in incident log"])
  q5 -->|"no"| esc
Governance Artifact

Operational Runbook

A specific, tested procedure for one alert — what to check, in what order, what to do, and when to stop and escalate.

quadrantChart
  title Platform technologies
  x-axis "Retire" --> "Adopt"
  y-axis "Low usage" --> "High usage"
  quadrant-1 "Adopt — default choice"
  quadrant-2 "Hold — in use, do not extend"
  quadrant-3 "Retire — plan removal"
  quadrant-4 "Trial / Assess — bounded use"
  "Kubernetes (managed)": [0.92, 0.88]
  "PostgreSQL": [0.95, 0.93]
  "Kafka (managed)": [0.86, 0.72]
  "Terraform": [0.90, 0.80]
  "OpenTelemetry": [0.78, 0.55]
  "Service mesh": [0.55, 0.30]
  "Self-managed Elasticsearch": [0.18, 0.62]
  "Oracle DB": [0.12, 0.70]
  "Jenkins": [0.20, 0.45]
  "Nomad": [0.60, 0.08]
  "DuckDB (analytics)": [0.62, 0.12]
Analysis Artifact

Technology Radar

What the organisation has decided to adopt, trial, assess or retire — a decision record about technology choice, not a fashion report.