Architecture Documentation and Communication Questions
Making an architecture legible to others: architecture decision records (templates, alternatives and consequences, lifecycle, supersession, tagging and discoverability), diagramming and visualization (C4, sequence, deployment, data-flow and trust-boundary diagrams, notation conventions), and communicating designs to technical and non-technical stakeholders. Covers capturing rationale, documenting what a system does under failure, load and consistency trade-offs, recording observability, SLO and security content, running design reviews, keeping docs and diagrams current, and presenting a system clearly under time pressure. The communication skill that separates a good design from an understood one.
Write a one-page ADR that documents the decision to standardise service orchestration on a single platform. What alternatives, rationale, migration risks and rollback plan belong in it, and how do you keep it to one page?
Sample Answer
Direct answer
Interpreting "service orchestration platform" as the runtime that schedules and runs your services (an orchestrator is software that decides which machine each copy of a service runs on, restarts crashed copies, scales copies up or down and rolls out new versions; Kubernetes is the most common one), versus each team choosing its own, a one-page ADR (architecture decision record: a short document capturing one decision) needs five things: the decision in one sentence, two or three alternatives, the rationale tied to a real pain, migration risks, and a rollback plan. It stays to one page by linking out, using tight bullets, and giving each section a line budget.
The one-page ADR
# ADR-12: Standardise service runtime on one container orchestrator
Status: Proposed | Date: 2026-09-28 | Owner: platform lead
**Decision.** All new and migrated services run on the managed Kubernetes
cluster (a cloud provider operates the cluster's control machinery for us). Other runtimes need a written exception.
**Context.** Six services run on four different platforms (VMs, two PaaS
(platform-as-a-service) products, hand-rolled scripts). Each has its own deploy, logging and
on-call setup, so incidents take longer to diagnose and new joiners learn
four systems.
**Alternatives.** (1) Keep team choice. (2) Serverless functions (code the cloud vendor runs on demand, with no servers to manage) for
everything. (3) One orchestrator (chosen).
Rejected 1: keeps the cost we are trying to remove. Rejected 2: poor fit
for long-running and stateful services.
**Rationale.** One deploy path, one observability setup, one skills base.
**Migration risks.** Team learning curve; two systems in parallel during
the move; noisy-neighbour effects on shared nodes (one service hogging a machine's CPU or memory and slowing the others); cost increase before
old platforms are retired.
**Rollback.** Migrate one service at a time. Keep the old deployment
warm until the new one has run a full release cycle; rollback is
re-pointing traffic. Stop the programme if two consecutive migrations
miss their success checks (the agreed targets: deploy time no worse than before, no rise in incident count).
**Review.** 6 months, against example targets: services migrated 0 of 6 today, target 6 of 6; deploy time 40 min today, target under 15 min; time to diagnose an incident 2 h today, target under 1 h.
How to keep it to one page
- Decision first, then a sentence per section. Bullets, not paragraphs.
- Link to the cluster design, cost model and migration runbook instead of pasting them.
- One decision only. Choice of service mesh (a layer that manages service-to-service traffic) or ingress (the entry point that routes outside traffic in) is a separate ADR.
- Cut anything a reader would not miss: history of how you got here belongs in the linked proposal.
ML variant: model-serving platform choice (optional extension, only if the interviewer steers to ML)
Same shape, different options. For serving machine-learning models, compare three hosting styles:
| Style | Good for | Watch out for |
|---|---|---|
| Containers on the standard orchestrator | Steady traffic, GPU (graphics processor) scheduling, custom runtimes, reuse of the platform | You own scaling, upgrades and GPU capacity |
| Serverless functions | Spiky or low traffic, small models, no idle cost | Cold starts (delay when a new instance loads the model), size and time limits, poor GPU support |
| Managed model hosting from a cloud vendor | Speed to launch, built-in autoscaling and monitoring | Cost at scale, lock-in (hard to move away later), less control over the runtime |
A reasonable commit: containers on the standard platform for steady, latency-sensitive models, and a managed service for experiments. State what would flip it: if traffic is very spiky and models are small, serverless wins.
Pitfalls
- Standardising without an exception path creates shadow platforms.
- A rollback plan that says "revert" without saying what stays running during the move.
- Listing benefits with no measurable check; the review line above is what makes the decision testable.
What belongs in the observability section of an architecture document for a service? How do you make it useful to an on-call engineer without turning it into a monitoring manual?
Sample Answer
Direct answer
The observability section of an architecture document should say what signals the service emits, what "healthy" means in numbers, where an on-call engineer looks first, and how to go from a symptom to a cause. It is a map to the monitoring system, not a copy of it: it holds the design intent and the stable names, while dashboards and alert rules live in the tooling, linked from here.
Contents (in this order)
- Service level indicators (SLIs) and objectives (SLOs): an SLI is a measured quality of the service (for example the fraction of requests that succeed); an SLO is the target for it. List the two to four that describe user-visible health.
- Golden signals per component: latency, traffic, errors, saturation (how full the resource is). These four come from Google's Site Reliability Engineering book and are widely used as a minimal set that covers most user-visible trouble.
- Signals mapped to the three telemetry types: metrics (numbers over time, cheap, good for alerting), traces (one request followed across services) and logs (event detail). For each SLI say which metric measures it, which trace shows why it slipped, and which log confirms the cause.
- Instrumentation points: where in the architecture telemetry is inserted (ingress, meaning where requests enter the service; outbound calls, queue consumers, database client), and the correlation ID (a unique ID passed along a request so its logs and traces can be joined).
- Alerts: each alert names the symptom, the SLO it protects, severity, and the runbook link (a runbook is a step-by-step guide for handling that alert). An SLA (service level agreement) is the contractual promise to customers; the SLO is set stricter than the SLA, and the error budget is the failure allowance the SLO leaves (a 99.9 percent SLO leaves 0.1 percent). Alert on symptoms users feel, not every internal cause.
- Dashboards and dependencies: links, and the upstream and downstream services with their own health pages.
- Known blind spots: what we cannot currently see.
Keeping it useful without becoming a monitoring manual
- Include only what a stranger woken at night needs; put threshold tuning and query syntax in the monitoring tool.
- One table, one page: signal, what it means, first action.
- Link, do not paste screenshots that rot.
Worked variants (each a small row set)
| Service | Signals in the doc | Insertion points | Reading it |
|---|---|---|---|
| Messaging service | Throughput (messages per second in and out), consumer lag (how many messages are waiting behind the consumer), error rate (failed publishes and dead-lettered messages) | Producer client, broker, each consumer | Rising lag with normal throughput means a slow or stuck consumer |
| Streaming pipeline | Events in and out per stage, end-to-end delay, checkpoint age | Source read, each transform stage, sink write, with a timestamp attached at ingestion | Delay growing at one stage localizes the bottleneck |
| Search service | SLI: fraction of queries answered under 300 ms (an illustrative target) and returning results; mapped to a latency metric, a trace of the slow query path and a log of query and index errors | Query API, index shard calls, cache | A latency SLI breach: metric shows when, trace shows which shard, log shows the reason |
What "healthy in numbers" looks like (illustrative targets to agree with the owning team):
| Service | Healthy means |
|---|---|
| Messaging | Consumer lag under 1,000 messages for 99 percent of the day, and dead-letter count 0 |
| Streaming pipeline | End-to-end delay p99 under 60 seconds, checkpoint age (time since the pipeline last saved its progress, so how much would be redone after a crash) under 2 minutes |
| Search | 99 percent of queries answered under 300 ms, error rate under 0.1 percent |
And the one-table deliverable for the search row:
| Signal | What it means | First action |
|---|---|---|
| p99 latency above 300 ms | Slow queries | Open the slow-query trace, look for the slow shard (a shard is one slice of the search index held on one server) |
| Error rate above 0.1 percent | Failed queries | Check the log for index errors, then recent deploys |
Pitfalls: alerts with no owner or runbook; listing hundreds of metrics; describing tools instead of decisions; no statement of what "healthy" is.
How would you standardise a documentation record of failure domains and blast radius for every service in a large architecture? Which fields would it require, and how would the record feed a failure-mode analysis?
Sample Answer
Direct answer
I would keep one small, structured record per service, stored as a file next to the service's code (so it is reviewed with changes), with fixed fields for where it can fail, what depends on it, and what breaks when it fails. Because the fields are machine-readable, a script can walk the dependency links to compute blast radius, and the same records feed a failure-mode analysis.
Terms
- Failure domain: a set of things that fail together (one process, one host, one availability zone (AZ), one region, one account, one third-party provider).
- Blast radius: how much of the system and how many users are affected when one thing fails.
- FMEA (failure mode and effects analysis): list each way a component can fail, the effect, and score severity, occurrence and detectability, each from 1 to 10. Their product is the risk priority number (RPN); higher means fix first. Scale direction matters: severity 10 is the worst impact, occurrence 10 is the most frequent, and detectability 10 means the failure is almost never caught (1 means it is always caught), so a hard-to-detect failure raises the RPN.
Required fields
| Field | Why |
|---|---|
| Service, owner, criticality tier | Who answers, how urgent |
| Failure domains it runs in | Shows shared fate (two "redundant" services in one AZ) |
| Hard and soft dependencies (sync or async) | Feeds the blast radius calculation |
| Failure modes and user-visible effect | Feeds the FMEA rows |
| Degraded mode / fallback | What still works |
| Detection signal and alert | Detectability score |
| Recovery objectives (RTO, RPO) | Recovery expectations |
| Single point of failure flag, last game-day date | Freshness and risk |
Plain meanings: a hard dependency is one the service cannot work without; a soft dependency can be skipped in a degraded mode. Sync means the service waits for the reply; async means it hands work off and continues. The criticality tier ranks how much the business suffers if the service is down (for example tier 1 = revenue-critical). A single point of failure is one component with no backup whose failure stops the service. A game-day is a rehearsal where the team deliberately breaks something to test detection and recovery. A failure mode is one specific way a component can fail.
One record filled in (illustrative, for the checkout service)
service: checkout
owner: payments-team
criticality_tier: 1
failure_domains: [region-a, az-1, az-2]
depends_on:
hard: [payments, inventory]
soft: [recommend]
failure_modes:
- mode: payments timeout
effect: users cannot pay
fallback: retry once, then show "try again" page
detection: payment error rate alert
rto: 15m
rpo: 1m
single_point_of_failure: false
last_game_day: 2026-06-10
Worked example (illustrative data, script run as shown)
What the script does: depends_on maps each service to the services it needs. To find who breaks when failed goes down, blast_radius repeatedly finds every service that depends on anything in the current set (the frontier), adds them to the affected list, and repeats until no new services appear. So stock-db breaks inventory and search, which in turn break checkout, which breaks web.
# who breaks when a service fails? reverse traversal of "depends_on"
depends_on = {
"checkout": ["payments", "inventory"],
"payments": ["card-gateway"],
"inventory": ["stock-db"],
"search": ["stock-db"],
"recommend": ["model-api"],
"web": ["checkout", "search", "recommend"],
}
def blast_radius(failed):
hit, frontier = set(), {failed}
while frontier:
nxt = {s for s, deps in depends_on.items() if frontier & set(deps)} - hit
hit |= nxt
frontier = nxt
return sorted(hit)
for svc in ["stock-db", "model-api"]:
print(svc, "->", blast_radius(svc))
# FMEA risk priority number = severity x occurrence x detectability (each 1-10, illustrative)
rows = [("model-api timeout", 6, 5, 3), ("model-api quota exhausted", 6, 4, 7), ("stale features", 4, 6, 8)]
for name, s, o, d in sorted(rows, key=lambda r: -(r[1]*r[2]*r[3])):
print(f"{name}: RPN = {s}*{o}*{d} = {s*o*d}")
Output:
stock-db -> ['checkout', 'inventory', 'search', 'web']
model-api -> ['recommend', 'web']
stale features: RPN = 4*6*8 = 192
model-api quota exhausted: RPN = 6*4*7 = 168
model-api timeout: RPN = 6*5*3 = 90
Worked FMEA rows for a third-party model API (the dependency behind the recommend service)
Rows for the model API: timeout (visible, so easy to catch: detectability score 3 on the scale where 1 is always caught and 10 is almost never caught), quota exhausted (the provider's usage limit is used up; silent until requests fail, hard to catch: score 7), stale features (silent quality loss, hardest to catch: score 8, so highest RPN). The record names the fallback for each (cached result, smaller local model, or explicit "recommendations unavailable"), and the third party is its own failure domain.
Trade-offs and pitfalls
- RPN scores are judgement, not measurement. Use them to rank, and have the owning team score them, not the author alone.
- Records rot. Tie a review to each game-day and to any dependency change.
- Blast radius here is service-level; user-percentage estimates need traffic data.
Which diagrams do you draw to describe a new distributed service, and what question does each one answer? What would you draw for a review with SREs versus for a mixed audience?
Sample Answer
Direct answer
No single diagram describes a distributed service, so I draw a small set where each answers one question: context (who and what surrounds the system), container (what deployable pieces it is made of), sequence (what happens over time in a key flow, including failure), deployment (where it runs), and, when needed, component (the inside of one complex container), data flow and state diagrams: seven in all, matching the table below. These follow the C4 model (Context, Container, Component, Code: four zoom levels) plus UML (Unified Modeling Language, a standard diagram notation) style sequence diagrams (participants across the top, time flowing down) and state diagrams (the states an entity moves through and what triggers each move). Start with context, container and sequence: those three are asked about most; data flow and state are occasional. For SREs (site reliability engineers, who run the service in production) I lead with deployment, component and failure sequence; for a mixed audience I show context, container and one happy-path sequence (the flow where nothing goes wrong).
Which diagram answers which question
| Diagram | Question it answers | Audience |
|---|---|---|
| System context | Who uses it, what external systems does it depend on? | Everyone |
| Container | What runs separately (apps, services, stores, queues) and how do they talk? | Engineers, architects |
| Component (one container only) | How is this complex service organised inside? | Owning team |
| Sequence | In what order do calls happen, where are timeouts and retries? | Engineers, SREs, QA |
| Deployment | Which zones, clusters, regions host what? | SREs, security |
| Data flow / trust | Where does sensitive data go? | Security, compliance |
| State | What lifecycle states can an entity be in? | Engineers, QA |
SRE review versus mixed audience
- SREs: a component view (the internal structure of one service) plus a deployment view, then a sequence of the failure path and the dependency list with timeouts. They want blast radius (how much breaks when one part fails), capacity and failover.
- Mixed audience (product, QA, engineering): context, container in plain names, and one narrated sequence. No cloud-icon wall, no acronyms without a legend.
Worked example: mobile client, API, auth service, database
- Context: User, Mobile app system, external identity provider.
- Container: Mobile app, API, Auth service, Database, each with a one-line responsibility.
- Sequence: app sends login, API asks Auth, Auth checks the database, token returns. Timeout on the Auth call is stated (for example 2 seconds).
That is three views for three questions, not one overloaded picture. The sequence for the login flow, drawn as Mermaid:
sequenceDiagram
participant M as Mobile app
participant A as API
participant U as Auth service
participant D as Database
M->>A: login(user, password)
A->>U: verify credentials (timeout 2 s)
U->>D: look up user
D-->>U: user record
U-->>A: token
A-->>M: token
And the container view as text, one line per box:
Mobile app -> API : HTTPS, JSON
API -> Auth : verifies credentials
Auth -> Database : reads user records
Conventions I apply to all of them
- Naming: use the same names as the code repository and dashboards, one name per thing.
- Tools: diagrams as code (Mermaid, PlantUML and Structurizr are text-based diagram tools; Mermaid is the easiest start because many Git hosts render it directly) kept in the repository so changes are reviewed in pull requests; a drawing tool for one-off workshop sketches.
- Annotate: state assumptions ("peak 500 requests per second, assumed"), non-functional requirements (NFRs, targets such as availability or latency), and a version and date on each diagram.
- QA audience: sequence and state diagrams are what testers turn into test cases, and the context view shows integration points to stub (replace with a fake in tests).
Trade-offs and pitfalls
- Drawing all diagrams for every service is wasted effort; draw the ones whose question is open.
- Mixing levels (a database next to a class name) is the most common defect and confuses every reader.
What is an Architecture Decision Record, and what makes a good one? Walk me through what it contains and when your team would write one.
Sample Answer
Direct answer
An Architecture Decision Record (ADR) is a short document that captures ONE significant architecture decision: the situation that forced it, what was chosen, what else was considered, and what the team accepted as a consequence. A good ADR is written at the time of the decision, is honest about the downsides, and is never silently rewritten later, so a future engineer can learn why the system looks the way it does, not just how.
What it contains
- Title and number: a short statement of the decision, such as "ADR-0007: Use gRPC for internal service calls". (gRPC is Google's remote procedure call framework; REST is the common style of calling services over plain HTTP with JSON.)
- Status: Proposed, Accepted, Rejected, Deprecated, or "Superseded by ADR-00NN".
- Context: the forces at play (requirements, constraints, team skills, deadlines) in a few sentences a newcomer can follow.
- Decision: one clear sentence in active voice ("We will...").
- Alternatives considered: the real options and why each lost.
- Consequences: what gets easier, what gets harder, and what new risks we now carry. Both good and bad.
- Date and deciders, so people know who to ask.
Worked example (REST vs gRPC)
ADR-0007: Use gRPC for calls between Orders and Pricing
Status: Accepted (2025-03-12)
Context: Orders calls Pricing on every checkout. Both are internal, both
are owned by us, and we want a typed contract (request and reply shapes declared in a schema, so a mismatch is a build error rather than a production surprise).
Decision: We will define the contract in protobuf (a compact, typed message format declared in a schema file) and call Pricing over gRPC.
Alternatives: REST+JSON (familiar, easy to debug with curl, a command-line tool for sending web requests, but the
contract is only documentation); message queue (decoupled, but checkout
needs the price synchronously).
Consequences: (+) generated clients, compile-time contract checks.
(-) browsers cannot call it directly, so the public edge stays REST;
(-) the team must learn protobuf tooling and gRPC debugging.
When your team writes one
Write an ADR when a decision is hard to reverse, affects more than one team, had real alternatives, or would make a new hire ask "why on earth did we do it this way?". Cross-team adoption works best when the ADR arrives as a pull request (a proposed change others review) in a shared or per-repo folder, so the discussion happens on the record and other teams can link to it or reuse it rather than re-deciding.
Storing, versioning and surfacing them so rationale survives years
- Keep them in version control next to the code (for example
docs/adr/0007-use-grpc-for-internal-calls.md), one file per decision, numbered and never deleted. Git history (the stored record of every change and who made it) then gives you versioning and authorship for free. - Treat accepted ADRs as append-only (you add new records but never rewrite old ones): to change your mind, write a new ADR and mark the old one "Superseded by ADR-0015", with a link in both directions.
- Maintain an index page (or publish the folder to the docs site) listing number, title, status and date, so people can search rather than browse.
- Link ADRs from the places engineers actually look: the service README, the pull request that implemented it, and the service catalog entry (the internal directory listing each service with its owner and docs). Auditors get a dated, reviewed, immutable (cannot be altered afterwards) trail.
Trade-offs and pitfalls
- Too long: nobody reads a five-page ADR. Aim for one page.
- Too many: writing ADRs for trivial choices creates fatigue and buries the important ones.
- Decision without alternatives or consequences reads as a press release, not a record.
- Editing history: rewriting an old ADR destroys the very evidence it exists to preserve.
Unlock Full Question Bank
Get access to all 25 Architecture Documentation and Communication interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.