Section 12

Architecture documents & governance

What each document is for, when it's written, who reads it and what goes in it: ACD, AIA, SO, HLD, LLD, ADR, SOP, plus NFRs, C4, threat models and runbooks, and the soft skills and governance that make the documents land.

Acronyms like ACD, AIA and SO mean different things in different organisations. The expansions below are the common ones. Check your organisation's templates and adjust the names, keeping the purpose.

12.1 Where each document fits

Documents get more detailed as an initiative moves from idea to operations. ADRs are written throughout.

πŸ’‘ Idea / demand
β†’
ACDconcept & context
β†’
AIAimpact & governance path
β†’
SO / HLDsolution design
β†’
LLDbuild detail
β†’
Build & test
β†’
SOP / Runbookoperate
πŸ“ ADRs: one per significant decision, at any stage
DocQuestion it answersAudienceDetail
ACDWhy are we doing this, and what's the concept?Business, sponsors, enterprise architectsLow
AIAWhat does it impact, and how risky is it?Architecture review board, risk, securityLow–medium
SO / HLDWhat's the solution, and how does it fit together?Architects, tech leads, delivery, securityMedium
LLDExactly how do we build it?Developers, testers, platform engineersHigh
ADRWhy did we choose X over Y?Current and future teamFocused
SOPHow do we operate it, step by step?Operations, support, SREProcedural

12.2 ACD: Architecture Concept / Context Document

The earliest architecture artefact. It frames the problem, the business context and the target concept before detailed design begins.

Typical contents

  • Problem statement and business drivers
  • Scope (in / out), stakeholders
  • Current state (as-is) context diagram
  • Target state concept (to-be), capabilities affected
  • Options considered (at a high level), recommended direction
  • Key assumptions, constraints, dependencies, risks
  • Alignment with enterprise strategy and principles
  • Keep it short and visual. Its job is to get agreement on direction.
  • One context diagram is worth pages of text (C4 level 1).
  • Capture options early so later reviews don't reopen them.

12.3 AIA: Architecture Impact Assessment

Assesses how a change affects existing systems, data, integrations, security, operations and cost, and decides how much governance it needs.

Typical contents

  • Change summary and classification (minor / major / strategic)
  • Impacted applications, interfaces, data stores
  • Data impact: classification, PII, residency, retention
  • Security and privacy impact, regulatory obligations
  • Infrastructure, operational and support impact
  • Technology standards compliance, technical debt created or removed
  • Risk rating β†’ governance path (fast-track vs full review board)
  • In AI programmes, "AIA" can also mean AI Impact Assessment: fairness, transparency, data use, human oversight, model risk.
  • Be honest about impacts. Surprises found later cost much more.

12.4 SO: Solution Outline / Solution Overview

A high-level description of the proposed solution: its components, integrations, key decisions and how it meets requirements. The bridge between concept and detailed design.

Typical contents

  • Requirements summary: functional + non-functional
  • Solution architecture diagram (C4 level 2: containers)
  • Components and responsibilities, build vs buy
  • Integration overview: interfaces, patterns (sync/async/batch), protocols
  • Data flows and data model overview
  • Security architecture (IAM, encryption, network zones)
  • Deployment and environments, HA/DR approach
  • Options analysis, key decisions (link ADRs), risks, costs
  • Explain how each NFR is met (availability target β†’ zone redundancy + DR region).
  • Show trade-offs. Reviewers trust designs that admit their weaknesses.

12.5 HLD: High-Level Design Added

The system-level design: major components, interactions, technology choices and deployment topology. In many organisations, the SO and HLD are one document.

How to implement it
Library / APIPackageUse it for
Aspire AppHostAspire.Hosting.AppHost (+ Aspire.Hosting.* integrations)The HLD topology as runnable C#: services, databases, queues and their references. The dashboard draws the live resource graph
Architecture testsTngTech.ArchUnitNET (+ .xUnitV3 / .MSTestV2)Fail the build when code breaks the layering in the HLD (e.g. API must not reference the data layer)
Cross-cutting defaultsAspire ServiceDefaults template (OpenTelemetry, health checks, resilience, service discovery)Apply the HLD's logging, monitoring and resilience decisions to every service the same way
// AppHost: the container view (C4 level 2) in code
var builder = DistributedApplication.CreateBuilder(args);
var redis = builder.AddRedis("cache");
var sql   = builder.AddSqlServer("sql").AddDatabase("payments");
var bus   = builder.AddAzureServiceBus("bus");

builder.AddProject<Projects.Payments_Api>("payments-api")
       .WithReference(sql).WithReference(redis).WithReference(bus);

builder.Build().Run();

NetArchTest.Rules is still popular, but it hasn't had a release since 2021. Prefer ArchUnitNET for new projects.

12.6 LLD: Low-Level Design

The developer-ready blueprint. It describes each component in enough detail to build and test without guessing.

Typical contents

  • Component internals: modules, classes, responsibilities
  • API contracts (OpenAPI), message schemas, event definitions
  • Database schema: tables, keys, indexes, partitioning
  • Detailed sequence diagrams, including error paths
  • Validation rules, mappings and transformations, business rules
  • Error handling, retries, idempotency, timeouts
  • Configuration, feature flags, secrets references
  • Logging and metrics events, alert definitions
  • Infrastructure specifics: SKUs, network rules, IaC modules
  • Test approach: unit, integration, performance
  • Keep it close to the code (in the repo, as Markdown + diagrams-as-code) so it doesn't drift.
  • Generated artefacts (OpenAPI, schema DDL) are better than hand-copied tables.
How to implement it
LLD artefactLibrary / APINotes
API contract (OpenAPI)built-in Microsoft.AspNetCore.OpenApi (AddOpenApi / MapOpenApi)Generated from the code; OpenAPI 3.1 by default in .NET 10. Add Microsoft.Extensions.ApiDescription.Server to write the file at build time
Message / event schemasbuilt-in JsonSchemaExporter (System.Text.Json.Schema)Export JSON Schema from your event record types
Database schemaEF Core migrations: dotnet ef migrations script --idempotentReviewable DDL generated from the model, not hand-copied tables
Layer and naming rulesTngTech.ArchUnitNETTurn LLD rules into tests
Validation rulesbuilt-in minimal API validation (AddValidation(), .NET 10) with DataAnnotationsRules live on the request types and show up in the OpenAPI document
// Program.cs
builder.Services.AddOpenApi();
app.MapOpenApi();                          // /openapi/v1.json

// Event schema for the LLD / schema registry
JsonNode schema = JsonSerializerOptions.Default.GetJsonSchemaAsNode(typeof(PaymentCompleted));

12.7 ADR: Architecture Decision Record

A short, immutable note recording one significant decision: its context, the options, the choice and the consequences. Your future self will thank you.

ADR-017: Use Azure Service Bus for payment event integration
Status:   Accepted (2026-03-04)   [Proposed | Accepted | Deprecated | Superseded by ADR-0xx]
Context:  Payment service must notify 4 downstream systems; needs ordering per account,
          DLQ, at-least-once delivery, enterprise support; volumes ~200 msg/s peak.
Options:  1) Service Bus topics  2) Event Hubs/Kafka  3) Direct REST calls
Decision: Service Bus topics with sessions (session = account ID) + transactional outbox.
Consequences:
   + ordering per account, DLQ, managed service, fits volumes
   βˆ’ not built for replaying history (use Event Hubs later if analytics streaming needed)
   βˆ’ consumers must be idempotent
  • Write ADRs for decisions that are hard to reverse or often questioned.
  • Never edit an accepted ADR. Supersede it with a new one, so the history is kept.
  • Store them in the repo (/docs/adr). Tools: adr-tools, Log4brains.
  • Formats: Michael Nygard's (above), MADR.

"Why on earth did we choose this?" πŸ€” Every team, 18 months later.

Fix: Architecture Decision Records. One page per big decision: Context β†’ Options β†’ Decision β†’ Consequences.

Never edit an old one, supersede it. Your architecture gets a memory.

#SoftwareArchitecture #ADR #EngineeringCulture

12.8 SOP: Standard Operating Procedure

Step-by-step instructions for a routine operational task, so it's done the same way every time, by anyone trained.

Typical structure

  1. Purpose and scope
  2. Roles and responsibilities (RACI)
  3. Prerequisites, access and tools needed
  4. Numbered steps with expected results (and screenshots or commands)
  5. Verification / success criteria
  6. Rollback or exception handling
  7. Escalation contacts
  8. Version, owner, review date

Examples

  • Certificate renewal and rotation
  • Monthly DR failover test
  • Onboarding a new API consumer in APIM
  • Replaying messages from a DLQ
  • Patching and release deployment

12.9 Non-Functional Requirements (NFRs) Added

Functional requirements say what the system does. NFRs say how well it does it. Make them measurable.

Performance

p95 < 300 ms at 500 TPS

Availability

99.95% monthly, excluding planned maintenance

Scalability

Handle 3Γ— peak with auto-scale

Recoverability

RPO 5 min, RTO 1 h

Security

OAuth2, TLS 1.2+, encryption at rest, OWASP

Compliance

Privacy Act, APRA CPS 234/230, PCI DSS

Observability

Traces, dashboards, alerts on SLOs

Maintainability & cost

Deployment frequency, cost per transaction

❌ "The system should be fast." βœ… "95% of balance enquiries respond within 300 ms at 1,000 req/s."
How to implement it
NFRLibrary / APINotes
Performance (code level)BenchmarkDotNetMicro-benchmarks for hot paths, run before and after changes
Performance (system level)NBomber check licence; Azure Load Testing (JMeter / Locust)Prove "p95 < 300 ms at 500 TPS" before go-live
Availabilitybuilt-in AddHealthChecks() / MapHealthChecks; AspNetCore.HealthChecks.* (Xabaril)Liveness / readiness probes for the load balancer and orchestrator
ResilienceMicrosoft.Extensions.Http.Resilience (AddStandardResilienceHandler)Timeouts, retries, circuit breakers on every outbound call
Observability / SLIsbuilt-in System.Diagnostics.Metrics + OpenTelemetry.Extensions.HostingASP.NET Core emits http.server.request.duration; build SLO dashboards and alerts on it
Scalability / abusebuilt-in Microsoft.AspNetCore.RateLimitingProtect capacity and enforce fair use

12.10 C4 model for diagrams Added

Four zoom levels of architecture diagrams, like Google Maps for software.

1. Contextsystem + users + external systems
β†’ zoom
2. Containerapps, APIs, DBs, queues
β†’ zoom
3. Componentmodules inside one container
β†’ zoom
4. Codeclasses (rarely drawn)
  • ACD β†’ level 1. SO/HLD β†’ levels 1–2. LLD β†’ levels 3–4. Diagrams-as-code: Structurizr, PlantUML, Mermaid.
How to implement it
ToolNotes
Structurizr DSL / Mermaid / PlantUML (text files in the repo)The recommended way to write C4 diagrams as code; no .NET package needed. Render in CI or in the docs site
Structurizr for .NET (Structurizr.Core)Exists, but its own README says it lags the Java version. Use it only if you must generate the model from C#
Aspire dashboard resource graphA live, always-accurate view of containers (level 2) for a running .NET system

12.11 Threat model (STRIDE) Added

Systematically ask "what could go wrong?" on your data-flow diagram, before attackers do.

STRIDEThreatTypical control
SpoofingPretending to be someone elseStrong authentication, MFA, mTLS
TamperingChanging dataIntegrity checks, signatures, TLS
RepudiationDenying an actionAudit logs, signing
Information disclosureData leakEncryption, access control, masking
Denial of serviceMaking it unavailableRate limits, WAF, auto-scale
Elevation of privilegeGaining more rightsLeast privilege, authZ checks
How to implement it

The Microsoft Threat Modeling Tool is a desktop app for drawing the data-flow diagram, not a library. The controls it recommends map to these .NET APIs:

STRIDE.NET control
SpoofingMicrosoft.Identity.Web / Microsoft.AspNetCore.Authentication.JwtBearer; mTLS with Microsoft.AspNetCore.Authentication.Certificate; Azure.Identity managed identities
Tamperingbuilt-in HTTPS + HSTS middleware; HMACSHA256 / ECDsa (System.Security.Cryptography) for message signatures
RepudiationStructured audit logs via ILogger + OpenTelemetry, with user ID and trace ID on every action
Information disclosurebuilt-in Data Protection API; Microsoft.Extensions.Compliance.Redaction; Azure.Security.KeyVault.Secrets
Denial of servicebuilt-in Microsoft.AspNetCore.RateLimiting; Kestrel request size and timeout limits
Elevation of privilegebuilt-in authorization policies (AddAuthorizationBuilder, RequireAuthorization), resource-based IAuthorizationService

12.12 Runbook vs SOP vs Playbook Added

SOP

Routine, planned tasks. The "how we always do X" procedure.

Runbook

Specific operational or incident steps for one system or alert ("if the DLQ depth is over 100, do…"). Often automated.

Playbook

Broader response strategy across teams for a scenario (cyber incident, regional outage, major release).

12.13 TOGAF & Well-Architected frameworks Added

Two widely used frameworks: TOGAF for running enterprise architecture, and Well-Architected for reviewing cloud workloads.

TOGAF ADM (enterprise architecture method)

Preliminary β†’ A. Vision β†’ B. Business β†’ C. Information Systems (data + application) β†’ D. Technology β†’ E. Opportunities & Solutions β†’ F. Migration Planning β†’ G. Implementation Governance β†’ H. Change Management, with Requirements Management at the centre.

Well-Architected (Azure / AWS)

Azure pillars: Reliability, Security, Cost Optimisation, Operational Excellence, Performance Efficiency. AWS adds Sustainability. Use them as a design review checklist.

12.14 Architect soft skills: trade-offs & stakeholders Added

Architecture is decisions plus persuasion. Make the trade-offs explicit, speak to each audience in its own language, and drive to a decision people will actually back.

Communicating trade-offs

Tailor to the audience

AudienceWhat they care aboutHow to present
Executives / sponsorsOutcome, cost, risk, time to marketOne page. Recommendation first, options in a simple table, the decision you need from them
Product ownersFeatures, customer impact, delivery datesWhat it enables, what it delays, the sequencing options
EngineersHow it works, constraints, effort, operabilityDiagrams (C4 level 2–3), contracts, NFRs, the alternatives you rejected and why
Risk, security, complianceControls, data flows, regulatory obligationsData-flow diagram, threat model, mapping to policies and standards

🀝 Influence without authority

Build relationships before you need them. Understand each stakeholder's goals and frame your proposal as helping them. Co-design with the teams who'll build it, so it's their idea too. Pre-wire decisions in 1:1s before the big meeting.

πŸ™… Say no with data

"No" becomes "Not like this, because…": show the numbers (cost, latency, incident history, risk rating). Offer an alternative or a "yes, if…". Escalate a decision you disagree with openly, with the trade-offs written down.

πŸ”Ž Run design reviews well

Send the document ahead of time with a clear question ("approve option A?"). Invite the right people, not everyone. Review against NFRs and principles, not taste. End with decisions, actions and owners, and record them as ADRs.

The one-page decision memo

1. Decisionwhat, by when
β†’
2. Context3–5 lines
β†’
3. Optionssame criteria
β†’
4. Recommendand why
β†’
5. Trade-offswhat we accept
β†’
6. Askapprove / fund / unblock
  • Every "it depends" needs an "on what". Name the drivers, then score the options against them.
  • Recommendation first. Executives want the decision and the risk. Engineers want the reasoning and the constraints.
  • Influence comes from trust, data and co-design, not job titles.
  • Finish every review with a recorded decision (ADR), actions and owners.

"It depends" is the most honest and the least useful answer an architect can give 🀷

Try "it depends β†’ on what" instead:

1️⃣ Name the 3–4 drivers: cost, latency, risk, skills.

2️⃣ Put 2–3 real options in a table, scored against the same drivers.

3️⃣ Lead with your recommendation and the trade-off you're accepting.

4️⃣ Say what would make you change your mind.

5️⃣ Write it down as an ADR.

Executives get a decision. Engineers get the reasoning. Everyone gets clarity.

#SoftwareArchitecture #SolutionArchitect #Leadership #DecisionMaking

12.15 Build vs buy, technical debt & governance Added

Build only what differentiates you. Manage technical debt like financial debt, deliberately and visibly. Govern with guardrails and paved roads, not just approval gates.

Build vs buy vs SaaS vs open source

πŸ› οΈ Build

Full control and a perfect fit. You own every bug, upgrade and on-call page, forever. For what makes you different.

πŸ“¦ Buy (COTS, self-hosted)

Proven features, vendor support. You still host and patch it. Customising it heavily makes upgrades painful.

☁️ SaaS

Fastest to start, no infrastructure. Less control over data location, roadmap and outages. Per-user costs grow with you.

🧩 Open source

No licence fee and you can inspect the code. You need the skills to run it, and you should check the licence and project health.

CriterionPoints to buildPoints to buy / SaaS
DifferentiationCore to your competitive edge (e.g. pricing engine, customer experience)Commodity (payroll, ticketing, email, identity)
TCO (3–5 years)Cheaper at scale once licences per user add upCheaper once you count the team to build, run and maintain it
Time to marketYou can wait monthsNeeded this quarter
Lock-inVendor would own a critical capability or your dataOpen standards and easy data export reduce the risk
SkillsYou have, or want to grow, the teamScarce skills, or not a capability you want to own
Regulation / dataStrict residency or control needs no vendor meetsVendor is certified (e.g. SOC 2, ISO 27001) and meets your requirements
Always write the exit plan before you sign: how you'd get your data out, in what format, how long migration would take, and what triggers leaving. For banks and other APRA-regulated entities, CPS 230 requires that you can exit a material service provider arrangement in an orderly way.

Technical debt: Fowler's quadrant

πŸ“’ Debt register

A visible list: the item, its impact ("adds 2 days to every release"), the interest (growing cost), the owner and a repayment plan. Link debt to ADRs so the reason is kept.

πŸ’° Debt budget

Reserve a fixed share of every sprint or quarter (often 15–20%) for paying down debt, instead of waiting for a "refactoring project" that never gets funded.

πŸ“ Fitness functions

Automated checks that guard an architecture characteristic: dependency rules, p95 latency, no vulnerable packages. They run in CI, so debt can't creep back in silently.

Architecture governance

🚧 Gates (use sparingly)

  • Review boards approve every design before build.
  • Slow, and it becomes a bottleneck.
  • Teams learn to work around it.
  • Keep gates for high-risk, hard-to-reverse decisions.

πŸ›€οΈ Guardrails + paved roads (default)

  • Guardrails: automated policies (Azure Policy, CI checks, fitness functions) that stop unsafe choices.
  • Paved roads / golden paths: templates and platforms that make the right way the easy way.
  • Teams on the paved road need little review. Leaving it requires an ADR.
Design authoritysets principles & standards
β†’
Paved roadtemplates, platform, defaults
β†’
Guardrailspolicy as code, fitness functions
β†’
Teams buildautonomously
β†’
ADRsfor exceptions & big decisions
  • Build what differentiates you, buy or subscribe for commodity. Compare 3–5 year TCO, and always write an exit plan.
  • Fowler's quadrant: reckless/prudent Γ— deliberate/inadvertent. Only prudent, deliberate debt is a real choice, so log it and plan the repayment.
  • Manage debt with a register, a standing budget and fitness functions in CI.
  • Guardrails over gates. Make the right way the easy way with paved roads, and use ADRs for exceptions.
How to implement it
Fitness functionLibrary / APINotes
Dependency and layering rulesTngTech.ArchUnitNET (+ TngTech.ArchUnitNET.xUnit)Architecture rules as unit tests that fail the build
Vulnerable or deprecated packagesbuilt-in dotnet list package --vulnerable --deprecatedRun in CI to stop dependency debt from piling up
using static ArchUnitNET.Fluent.ArchRuleDefinition;

public class ArchitectureTests
{
    static readonly Architecture Arch = new ArchLoader()
        .LoadAssemblies(typeof(Payment).Assembly, typeof(PaymentsDbContext).Assembly)
        .Build();

    [Fact]
    public void Domain_does_not_depend_on_infrastructure() =>
        Types().That().ResideInNamespace("Payments.Domain")
            .Should().NotDependOnAny(Types().That().ResideInNamespace("Payments.Infrastructure"))
            .Check(Arch);
}

Build vs buy is really "what makes us different?" 🧭

πŸ› οΈ Build what differentiates you: pricing, customer experience.

☁️ Buy or subscribe for commodity: payroll, ticketing, identity.

πŸ’° Compare 3–5 year TCO, not the licence price.

πŸšͺ Write the exit plan before you sign.

πŸ“’ Then manage tech debt like real debt: a register, a budget, and fitness functions in CI.

πŸ›€οΈ Govern with guardrails and paved roads, not approval queues.

What's the best build-vs-buy call you've seen?

#SoftwareArchitecture #TechDebt #BuildVsBuy #EnterpriseArchitecture

⚑ Quick-fire Q&A

HLD vs LLD?

HLD covers what components exist and how they interact (system view). LLD covers how each component is built: contracts, schemas, logic, error handling (developer view).

When do you write an ADR?

For any decision that is significant, costly to reverse, or likely to be questioned later: technology choice, integration pattern, data store, security approach.

What makes a good architecture document?

Clear purpose and audience, diagrams first, measurable NFRs, explicit trade-offs and decisions, linked ADRs, owner and version, and kept up to date.

How do you present a trade-off to executives vs engineers?

Executives: one page, recommendation first, cost, risk and time, and the decision you need from them. Engineers: the drivers, the options you rejected and why, diagrams, NFRs and constraints. Same decision, different level of detail.

How do you decide build vs buy?

Build what differentiates the business. Buy or use SaaS for commodity capabilities. Compare 3–5 year TCO (including the team to run it), time to market, lock-in, skills and regulatory fit, and write the exit plan before you sign.

What is Fowler's technical debt quadrant?

Two axes: reckless vs prudent, and deliberate vs inadvertent. Prudent, deliberate debt ("ship now, fix later") is a legitimate trade-off if you log it and plan repayment. Reckless debt needs better skills and guardrails. Prudent, inadvertent debt is normal learning, so refactor as you go.

← 11 Β· Architecture Patterns