Writing code is the easy part of being an architect; defending why the system looks the way it does, under questioning, months after the decision was made, is the actual job. Interviewers at the architect level spend less time asking what a pattern is and more time asking how you would decide between two defensible options, how you would know if that decision was wrong, and how you would explain it to someone who does not read code. This page covers the mechanics of good architectural decision-making: eliciting the quality attributes that actually matter, running a trade-off analysis that survives scrutiny, writing architecture decision records people actually read later, encoding constraints as fitness functions instead of wiki pages, and knowing when a decision deserves an hour of debate versus a week of it.

Q1 What are architecturally significant quality attributes, and how do you elicit them from stakeholders who cannot articulate what they want?#

Short answer: Quality attributes are the non-functional requirements that shape structure rather than behavior — performance, availability, scalability, security, maintainability, testability — and you elicit them not by asking "what are your non-functional requirements," which nobody can answer cold, but by asking concrete, scenario-based questions about what happens under specific failure and load conditions.

Stakeholders are fluent in features and almost never fluent in quality attributes, so the elicitation technique that works is turning abstract "-ilities" into scenarios they can react to: instead of "what's your availability requirement," ask "if this system is down for fifteen minutes at 2 PM on a weekday, what happens downstream, and who calls whom." That produces an actual number and an actual owner, where "high availability" produces neither. The same technique applies across attributes: for performance, ask about the slowest acceptable response time for the specific action a user is mid-task on; for security, ask what the worst plausible outcome of a breach is in business terms — regulatory fine, customer trust, contractual liability — rather than asking for a compliance checklist. A useful discipline is writing each attribute as a testable scenario with a stimulus, an environment and a measurable response, the format the ATAM (Architecture Tradeoff Analysis Method) approach uses: "A user submits an order during a flash-sale spike (3x normal load); the system must respond within 800ms for 99% of requests without dropping orders." That can be designed for and verified; "fast and reliable" cannot. It is also worth prioritizing attributes against each other early, because most interesting decisions trade off two attributes that both matter — consistency versus availability, time-to-market versus maintainability — and a stakeholder who has not been forced to rank them will assume they can have all of them at once.

What interviewers look for: the scenario-elicitation technique specifically, and awareness that quality attributes are frequently in tension with each other, which is the detail that separates someone who has actually run a requirements workshop from someone reciting the ISO 25010 attribute list.

Common mistakes: accepting "make it scalable" or "make it secure" as a requirement without translating it into a measurable scenario, which guarantees a dispute later about whether the requirement was actually met.

Q2 Walk through a structured trade-off analysis between two competing architecture options.#

Short answer: Lay both options against the same set of prioritized quality attributes, score each option's expected impact on each attribute (not just list pros and cons), explicitly separate factual claims from assumptions and risks, and make the trade points — where improving one attribute costs you another — visible rather than buried in prose, so the final choice is traceable back to which attributes the business actually prioritized.

The failure mode a plain pros-and-cons list falls into is treating every point as equally weighted and independent, when most architecture trade-offs actually come down to two or three attributes that matter far more than the rest. A weighted matrix forces that prioritization into the open: list the agreed quality attributes as rows, the candidate architectures as columns, and score each cell, then multiply by a weight reflecting how much the business cares about that attribute this year. This does not remove judgment, but it makes the judgment auditable — six months later, the answer to "why B over A" is "because we weighted operability higher than throughput, and here is why," not "it felt right at the time." Alongside the scoring, name the trade-off points explicitly: adopting an event-driven design over a synchronous one typically trades lower coupling and better resilience for higher operational complexity and weaker read-your-writes consistency — stating that trade sentence directly is more valuable than any score in the matrix.

Quality attributeWeightOption A scoreOption B score
Time to market384
Operational complexity273
Long-term extensibility348
Team familiarity195

What interviewers look for: a repeatable method rather than an ad hoc gut call, and the instinct to state the actual trade-off sentence in plain language instead of hiding behind a score.

Common mistakes: running the matrix with unweighted or unprioritized attributes, which just produces a tie and defers the real decision instead of making it.

Q3 What is an Architecture Decision Record, and what makes one actually useful when someone rereads it a year later?#

Short answer: An ADR is a short, immutable document that captures one significant architectural decision, the context that drove it and the consequences accepted at the time — the format popularized by Michael Nygard uses Title, Status, Context, Decision and Consequences — and what makes it useful later is recording the rejected options and why, not just the choice that won, because the question a future reader actually has is "did we consider this obvious alternative, and why did we rule it out."

The discipline that matters most is treating an ADR as a historical record, not a living document: once accepted, you do not edit it to reflect new information, you write a new one that supersedes it and links back, exactly like a changelog. This is what makes ADRs valuable during an incident or later redesign — you can read the full sequence of decisions and reversals in order, with each one's original context intact, rather than a document silently rewritten until it no longer explains what anyone was thinking. The context section is where most weak ADRs fail: it should capture the constraints and priorities in play at the time, including ones that later turned out wrong, because "we assumed traffic would stay regional" is exactly the sentence that explains a confusing decision two years later. The consequences section should be honest about downsides accepted, not just benefits claimed — an ADR listing only upsides reads as marketing, not a decision record.

Text
# ADR-014: Use an outbox table instead of a distributed transaction for order events

## Status
Accepted (supersedes ADR-009)

## Context
Orders and notifications are owned by separate services. A prior two-phase-commit
approach (ADR-009) caused availability incidents when the notification service was
slow, and does not fit the message broker we standardized on in ADR-012.

## Decision
Write order state changes and an outbox row in one local transaction; a relay
process publishes outbox rows to the broker.

## Consequences
Consumers must handle at-least-once delivery and duplicate events. Adds a relay
process to operate and monitor. Removes the availability coupling from ADR-009.

What interviewers look for: naming the standard sections, and specifically the discipline of recording rejected alternatives and honest consequences rather than treating an ADR as a one-line changelog entry.

Common mistakes: editing old ADRs in place instead of superseding them, and writing consequences sections that list only benefits.

Q4 What are fitness functions, and how would you implement one in a .NET codebase?#

Short answer: A fitness function is an automated, objective check that verifies an architectural characteristic continues to hold as the codebase evolves — the term comes from evolutionary architecture, by analogy with the fitness function that scores a candidate solution in an evolutionary algorithm — and in .NET it is typically implemented as a test, run in CI, that inspects the compiled assemblies or dependency graph rather than testing runtime behavior.

The point of a fitness function is converting an architectural rule that would otherwise live only in a document or a senior engineer's memory into something that fails a build the moment it is violated, the same way a unit test protects business logic. Common examples in a .NET solution: a test asserting the Domain project has no reference to Entity Framework or ASP.NET Core, protecting a Clean Architecture dependency rule; a test asserting no type outside a module's Contracts namespace is public, protecting a modular monolith's boundaries; or a performance fitness function that fails a build if a benchmarked hot path regresses past an agreed latency budget. Libraries like NetArchTest give a fluent API for dependency-direction checks directly against System.Reflection metadata, and nothing stops a team writing the equivalent by hand when a library does not cover the rule. The important design choice is where it runs: rules cheap enough for every commit (dependency direction, naming, visibility) belong in the regular CI pipeline; rules needing a realistic environment (latency under load) belong in a scheduled or pre-release stage, since gating every commit on a full load test is not sustainable.

C#
[Fact]
public void Domain_Should_Not_Depend_On_Infrastructure()
{
    var result = Types.InAssembly(typeof(Order).Assembly)
        .That().ResideInNamespace("Contoso.Domain")
        .ShouldNot().HaveDependencyOnAny("Microsoft.EntityFrameworkCore", "Contoso.Infrastructure")
        .GetResult();

    Assert.True(result.IsSuccessful, string.Join(", ", result.FailingTypeNames ?? []));
}

What interviewers look for: a concrete implementation approach (reflection-based dependency tests in CI), not just a definition, and judgment about which rules belong on every commit versus a slower pipeline stage.

Follow-up questions:

  • How would you write a fitness function for a rule that is hard to express structurally, like "services must not call each other synchronously more than two levels deep"?
  • What do you do when a fitness function starts failing because the rule itself needs to change?

Q5 How do you evaluate whether to adopt a new technology, library or pattern into an existing system?#

Short answer: Run a time-boxed spike against your actual constraints, not the vendor's demo, with explicit exit criteria decided before you start — what result would make you say yes, what result would make you say no — and weigh the total cost of ownership (operational burden, hiring pool, exit cost if it fails) at least as heavily as the feature capability that attracted you to it in the first place.

The most common failure is falling in love with a capability demonstrated in isolation and skipping what it costs to operate once it is one of thirty dependencies a year from now: who patches it, who is on call for it, how hard is it to hire for, and what does migrating away look like if it is the wrong bet. A disciplined evaluation writes exit criteria as a short, falsifiable list before the spike starts — for example, "adopt if it handles our peak write throughput with headroom, integrates with our existing auth without a bespoke adapter, and a team member unfamiliar with it can ship a small feature within two days" — because it is easy to rationalize a "yes" after time has been invested, and pre-committing protects against that bias. The spike should target your actual hardest constraint, not the easy path: benchmark your real write pattern under contention, not a generic vendor number measured under favorable conditions. Finally, weigh reversibility explicitly: a technology cheap to adopt but expensive to remove deserves a higher bar of evidence than one behind a clean abstraction that could be swapped later.

What interviewers look for: exit criteria defined before the spike, evaluation against the system's actual hardest constraint rather than a vendor demo, and total cost of ownership treated as a first-class factor rather than an afterthought.

Common mistakes: running a proof of concept against a toy dataset or the happy path only, and treating "the demo was impressive" as sufficient evidence to commit.

Q6 Distinguish reversible and irreversible architecture decisions, and explain how that distinction should change your decision-making process.#

Short answer: A reversible decision — sometimes called a two-way door — can be undone at acceptable cost if it turns out wrong, so it should be made quickly, often by the person or team closest to the problem, without escalating to a lengthy review; an irreversible, or one-way-door, decision is expensive or impossible to walk back, so it deserves slower, more deliberate analysis, wider input, and explicit sign-off before committing.

Most decisions people agonize over are actually reversible once you look honestly at the cost of reversal: a logging library, a caching strategy behind an abstraction, or an internal API's exact shape can all change later at bounded cost, and treating these with the ceremony of a genuinely irreversible decision slows a team down for no safety benefit. The decisions deserving heavier process are the ones where reversal cost is asymmetric and high: a primary data store the whole schema will be built around, a multi-tenant isolation model, a message broker every service integrates against directly, or a public API contract partners depend on — these warrant wider review and a written ADR precisely because getting it wrong is expensive to fix. The practical technique for making more decisions reversible is designing a seam at the point of highest uncertainty — hiding a new dependency behind an interface you own — which converts a one-way door into a two-way one at the cost of a little indirection, and is usually worth it exactly when confidence is lowest.

C#
// Wrapping a new provider behind an interface you own turns an otherwise
// hard-to-reverse vendor choice into a swappable implementation detail.
public interface IFeatureFlagProvider
{
    Task<bool> IsEnabledAsync(string flagKey, CancellationToken cancellationToken);
}

internal sealed class LaunchDarklyFeatureFlagProvider(ILdClient client) : IFeatureFlagProvider
{
    public Task<bool> IsEnabledAsync(string flagKey, CancellationToken cancellationToken) =>
        Task.FromResult(client.BoolVariation(flagKey, user: LdContext.Default(), defaultValue: false));
}

What interviewers look for: matching process weight to actual reversal cost rather than applying uniform ceremony to every decision, and the concrete technique of abstracting away uncertainty to convert a one-way door into a two-way one.

Common mistakes: treating every decision as irreversible out of caution, which produces analysis paralysis on choices that genuinely did not deserve a week of debate.

Q7 How do you communicate a complex or unpopular architecture decision to stakeholders who do not have a technical background?#

Short answer: Translate the decision into the vocabulary stakeholders already use for their own decisions — cost, time, risk and what the business can and cannot do afterward — instead of the vocabulary you used to make it, lead with the recommendation and its business consequence before the technical justification, and be explicit and quantified about the trade-off being accepted rather than presenting the decision as risk-free.

The translation step is the one architects skip most often: "we're moving to event-driven for better decoupling" means nothing to a product stakeholder, but "this lets two teams ship independently instead of coordinating every release, at the cost of data taking a few seconds longer to appear consistently" is something they can weigh against a roadmap. Leading with the recommendation, rather than building up to it through technical reasoning, respects that a stakeholder's real question is "what do I need to know to make my own decisions," and burying that under twenty minutes of diagrams reads as evasive even when the intent is thoroughness. Being explicit about the trade-off in both directions builds durable trust: stating plainly that a decision reduces long-term cost but increases short-term delivery risk means that when that risk materializes, it was expected, not a sign the decision failed. It is also worth pre-empting the questions a stakeholder will actually ask — cost, timeline, what happens if it's wrong — with direct answers rather than waiting to be asked.

What interviewers look for: the ability to actually produce the translated sentence on the spot, not just claim you would "communicate clearly" — this question is often asked as a live exercise where you have to reframe a technical decision in front of the interviewer.

Q8 Describe an architecture decision you made that later turned out to be wrong. How did you detect it, and what did you do?#

Short answer: Pick a decision where the reasoning was sound given what was known at the time — not a careless mistake — describe the specific signal that revealed it was wrong (a metric drifting, a quality attribute you under-weighted turning out to matter more than expected), and walk through the correction as a deliberate new decision with its own trade-offs, ideally referencing how you documented the reversal rather than quietly reworking the system.

The structure interviewers are listening for is closer to a short ADR narrated out loud than a confession: context at the time, the decision and why it looked right given the priorities then in play, the concrete evidence that surfaced later, and the corrective action, including what it cost to reverse. A strong version of this answer names a genuine trade-off that shifted — for example, a caching strategy chosen to optimize for read latency that later caused stale-data incidents once a downstream consumer's consistency needs grew beyond what was originally scoped — rather than a decision that was simply careless or under-researched, because the point of the question is judgment under uncertainty, not an admission of negligence. Equally important is describing detection: did you catch it from a metric you were already watching, from an incident, from a stakeholder complaint, or only in hindsight during an unrelated review — a candidate who monitors the consequences of their own decisions and catches drift early demonstrates more maturity than one who only discovers a bad call when it becomes a fire. Closing with how the correction was made — ideally as a new, superseding decision recorded the same way the original one was — ties this answer back to the ADR discipline covered earlier and shows the practice is not just theoretical.

What interviewers look for: a decision that was reasonable given the information available at the time, honest ownership of the outcome, a credible detection mechanism, and a corrective action treated as a first-class decision rather than a quiet, undocumented fix.

Common mistakes: choosing an example that was obviously careless rather than a genuine trade-off, or glossing over how the mistake was detected, which is often the more revealing half of the answer.

Q9 How do ADRs fit into a team's workflow without becoming bureaucratic overhead that nobody reads?#

Short answer: Write ADRs only for decisions that meet a defined bar of significance — expensive to reverse, cross-team impact, or a real trade-off between competing quality attributes — keep each one short enough to read in five minutes, store them next to the code they govern so they surface naturally in review, and treat writing one as part of the decision itself rather than paperwork that follows it.

The overhead problem almost always comes from applying ADRs too broadly: a team that writes one for every pull request drowns the significant decisions in noise, while a team that reserves them for decisions meeting a "would a new senior engineer need this context to avoid repeating a mistake" bar keeps the collection small enough to actually read. Storing ADRs as Markdown files in the repository, in a conventional docs/adr folder, rather than a separate wiki, matters more than it sounds: an ADR then shows up in the same review, search and version history as the code it explains, instead of a tool nobody opens unless they already know to look. Making ADR-writing part of the decision process, not a retrospective summary, produces better documents too — writing context and trade-offs down forces the same rigor a good trade-off analysis requires, and decisions that seemed obvious in a meeting often have unstated assumptions once someone tries to write them clearly. A short index listing every ADR by title and status, kept current, is what makes the collection navigable once it grows past a dozen entries. A lightweight CI check that fails a pull request touching a significant area without a corresponding new or updated ADR file is a low-effort way to keep the practice from quietly lapsing once the person who championed it moves on.

Bash
# CI check: a change under src/Payments/ without a matching new ADR fails the build,
# nudging significant changes toward a recorded decision instead of relying on memory.
if git diff --name-only "$BASE_SHA" | grep -q '^src/Payments/' && \
   ! git diff --name-only "$BASE_SHA" | grep -q '^docs/adr/.*\.md$'; then
  echo "Changes under src/Payments/ should include a new or updated ADR." && exit 1
fi

What interviewers look for: a defined significance threshold rather than "write one for everything," and storing decisions as part of the codebase rather than a separate, easily ignored tool.

Common mistakes: writing an ADR after the decision has already shipped, purely as after-the-fact documentation, which loses the forcing-function benefit of writing down trade-offs before committing to them.

Q10 How do you evaluate a build-versus-buy-versus-open-source decision for a significant architectural capability, such as a message broker or an identity provider?#

Short answer: Score all three paths against the same prioritized quality attributes used for any other architecture decision, but add two factors specific to this kind of choice — total cost of ownership over multiple years, not just license price, and the org's actual operational maturity for the option being considered — because the most common mistake is comparing a vendor's sticker price against an open-source option's zero license fee while ignoring the engineering time required to run either one well.

Buying a managed capability trades ongoing license cost for reduced operational burden and faster delivery, and is usually the right default when the capability is not a source of competitive differentiation — few companies win by running a better OAuth server than a specialist vendor's. Open source shifts cost from license fees to engineering time: running your own identity provider or broker is often cheaper in direct spend but requires real operational maturity — patching, scaling, securing, on-call — that a smaller team frequently underestimates until the first incident. Building in-house is justified far less often than engineers assume, and is defensible mainly when the capability is genuinely differentiating, no existing option fits a hard constraint, or the org already has deep expertise in that exact domain; "we don't like the options" is not, alone, sufficient given the ongoing cost a home-grown platform capability accumulates. Price in exit cost for each option too, since a vendor with proprietary APIs can be as hard to leave as a poorly abstracted in-house system.

What interviewers look for: total cost of ownership and operational maturity treated as decisive factors rather than sticker price, and healthy skepticism toward "build" as a default rather than a rare, well-justified exception.

Follow-up questions:

  • How would your recommendation change if the capability in question were closer to the org's core differentiator?
  • What specific evidence would change a "buy" recommendation into a "build" one?

Quick-Fire Round#

QuestionAnswer
What technique turns a vague requirement like "make it fast" into something testable?Writing it as a stimulus/environment/response scenario.
What are the five standard sections of a Nygard-style ADR?Title, Status, Context, Decision, Consequences.
What should you do with an ADR when the decision changes?Write a new ADR that supersedes it; never edit the original in place.
What is a fitness function, in one sentence?An automated check that verifies an architectural characteristic continues to hold.
What .NET technique commonly implements a dependency-direction fitness function?A reflection-based test, such as one written with NetArchTest.
What should you define before running a technology spike?Explicit exit criteria for what counts as a yes or a no.
What is a "two-way door" decision?A reversible decision, safe to make quickly without heavy process.
What technique converts a one-way door into a two-way one?Hiding the uncertain choice behind an interface or abstraction you own.
What vocabulary should replace technical jargon when briefing non-technical stakeholders?Cost, time, risk and what the business can or cannot do afterward.
What is the most common mistake in a build-vs-buy comparison?Comparing sticker price while ignoring total cost of ownership and exit cost.

How to Prepare#

  • Practice turning a vague stakeholder request into one written quality-attribute scenario, live, since this is often asked as an exercise rather than a definition question.
  • Be able to write a short ADR from memory, including a plausible rejected alternative, not just the accepted decision.
  • Have a concrete fitness function example ready in C#, and know which architectural rules belong in every-commit CI versus a slower pipeline.
  • Rehearse translating one real technical trade-off into a single stakeholder-facing sentence that states cost, time and risk explicitly.
  • Prepare a generic story about a decision you later reversed, framed around how you detected it was wrong, not just that it was.
  • Know the reversible-versus-irreversible framing well enough to sort a list of example decisions into each bucket on the spot.