Every design process produces decisions. Most design processes produce very little record of why those decisions were made, what alternatives were considered, and — most importantly — what the best argument against the chosen approach was and why it was rejected. The absence of this record is not a documentation problem. It is an intellectual honesty problem, and it has a specific downstream cost: when circumstances change, when the decision needs to be revisited, when a new team member asks why the system works the way it does, there is nothing to examine. The decision is present in the code. The reasoning is nowhere.
The Architecture Decision Record — ADR — is the antidote to this. In its full form, it is a short document that captures the context that made a decision necessary, the decision itself, the alternatives that were considered and rejected, the consequences the decision carries, and — in the version I consider essential — a direct rebuttal to the strongest objection that could be raised against it. That last field is the one that makes an ADR a design artefact rather than documentation. Anyone can write down what they decided. Writing down the best argument against your decision, and answering it honestly, requires something more: the intellectual confidence to have actually tested the decision before committing to it.
This article walks through three ADRs from real design work — two from an autonomous deal desk pipeline and one from an enterprise knowledge graph system — with full context, alternatives, consequences, and the objection each decision had to survive. The goal is not to justify those specific decisions. It is to show what an ADR looks like when it is doing its job.
The anatomy of an ADR that earns its place
The ADR format has been described by Michael Nygard and formalised in various templates over the years. The core structure — context, decision, consequences — is widely reproduced. What is less consistently applied is the constraint that distinguishes a useful ADR from a ceremonial one: the requirement that the rejected alternatives be named with their actual reasons for rejection, not dismissed; and that the primary objection to the accepted decision be stated directly and answered.
The table below maps each field to its purpose and the question it must answer to be considered complete. The Rebuttal field is marked optional in some templates. I treat it as required for any decision that involves a meaningful trade-off — which is to say, any decision worth recording at all.
ADR in practice: three decisions, three rebuttals
What follows are three Architecture Decision Records drawn from real design work. They are presented in the format described above, with the Rebuttal field treated as a required element. Each is accompanied by a brief commentary on what made the decision difficult and what the rebuttal had to actually establish — not just assert.
Decision one: the orchestration framework choice
The first decision concerns the orchestration layer of an autonomous deal desk: a GCP-native agentic pipeline that processes inbound Salesforce opportunities and generates compliant quote documents without human intervention below a configurable value threshold. The orchestration layer must implement a ReAct loop with tool-calling, state management, retry handling, and first-class interrupt nodes for HITL. The candidate options were the Vertex AI Agent SDK and a custom Python implementation against the Gemini API directly.
The objection this decision had to survive was not a weak one. Framework portability is a real consideration in enterprise deployments, and the argument for avoiding GCP lock-in is made by competent architects with good reasons. The rebuttal had to establish not just that the Vertex AI SDK was better for this use case, but that accepting the lock-in was the right trade-off given the defined deployment boundary. That is a different, and more honest, argument than "Vertex AI is better."
Custom Python ReAct: Maximum flexibility, but no managed observability, no built-in retry, no quota enforcement. Implementation surface increases by an estimated 40% without proportionate capability gain. Maintenance cost shifts entirely to the team.
Vertex AI Reasoning Engine: Higher abstraction layer, less control over the ReAct loop topology. HITL interrupt nodes require first-class graph primitives that Reasoning Engine does not expose at the required granularity.
Objection: LangGraph is framework-agnostic and avoids GCP lock-in, which should be the default posture for any enterprise architecture.
This objection is architecturally valid as a general principle. The rebuttal is not that lock-in is acceptable — it is that portability is not free, and the cost must be evaluated against the defined deployment boundary. This system is GCP-native by design: AlloyDB, Chronicle, Workload Identity, VPC Service Controls, Cloud KMS. The portability benefit of a framework-agnostic orchestrator is only realised if the other components are also portable. They are not. Accepting framework portability at the orchestration layer while maintaining GCP-specific infrastructure at every other layer is a false compromise: it adds the complexity of avoiding lock-in without delivering the benefit. If the deployment boundary changes — if multi-cloud becomes a real requirement — the correct response is to re-evaluate this ADR with the new constraint, not to pre-optimise for a requirement that does not yet exist.
Decision two: the vector store selection
The second decision concerns the storage layer for contract precedent embeddings in the same pipeline: approximately 500,000 document chunks, retrieved by approximate nearest-neighbour search with metadata filters applied at query time. The candidate options were AlloyDB with the pgvector extension and Vertex AI Vector Search.
This is a canonical "managed service versus integrated service" trade-off, and the objection to the chosen approach — that Vertex AI Vector Search is the more scalable, lower-operational-overhead option — is one that Google's own documentation would support. The rebuttal has to be specific about the boundary condition at which AlloyDB is the right answer, and what the documented migration path is when that boundary is crossed.
Pinecone: Best-in-class ANN recall and query performance. Rejected because it introduces a third cloud dependency in a GCP-native system, and its metadata filtering model, while capable, would require the same cross-service join problem as Vector Search.
BigQuery ML vector search: Suitable for batch retrieval; online ANN latency at sub-200ms is not achievable at the required consistency level. Not suitable for the 90-second end-to-end deal processing target.
Objection: Vertex AI Vector Search is fully managed, scales to billions of vectors without operational overhead, and is the correct default choice for any GCP-native vector retrieval use case.
At billion-scale corpora, this objection is decisive and AlloyDB would be the wrong choice. The rebuttal is specific to the 500K–5M chunk range and the filter-plus-vector query pattern. At this scale, the operational overhead of AlloyDB — HA configuration, index management — is bounded and well-understood. The cross-service join that Vertex AI Vector Search would require adds latency that is directly measurable: in testing, the metadata post-filter join adds 40–80ms to query time, which represents a meaningful fraction of the 90-second end-to-end target for a multi-step pipeline. The decision is not "AlloyDB is better than Vector Search." It is "AlloyDB is better for this query pattern at this corpus scale, with a documented graduation path when the scale changes." The graduation path is specified in the Day 2 operations runbook. This ADR is a time-bounded decision, not a permanent one.
Decision three: the knowledge graph store
The third ADR comes from a different project: an enterprise knowledge graph system that models relationships between people, expertise, engagements, and methodologies for a professional services firm. The graph store choice was between Neo4j Aura Enterprise and Amazon Neptune. This decision is worth examining in detail not because of the technology choice, but because of what the context section reveals: the decision was not primarily about graph performance. It was about query language standardisation, operational network topology, and the team's existing skill set.
The objection this decision had to survive was the cross-cloud dependency argument — which is a real architectural concern, not a weak one. The rebuttal required establishing that GCP-native network peering with Neo4j eliminated the primary operational objection to a third-party graph database in a GCP-native system.
Spanner Graph: Would eliminate the third-party graph dependency entirely. Rejected because Spanner Graph was in preview status at the time of this ADR with insufficient APOC-equivalent procedure library for the ontology management operations required. Documented as the re-evaluation candidate when Spanner Graph reaches GA with APOC parity.
Objection: A GCP-native system should not depend on a third-party database product from a different cloud vendor. Amazon Neptune at least offers a managed service on a major cloud with established enterprise SLAs; Neo4j Aura introduces a third vendor dependency with its own availability risk and pricing model.
This objection frames the choice as "GCP-native vendor" versus "third-party vendor," which is the wrong frame for this decision. The actual choice is between: (a) a graph database with native GCP Private Service Connect, CMEK integration, and a query model the team knows, deployed as a GCP-managed service partnership; and (b) a graph database on a different cloud, requiring cross-cloud network bridging, egress cost management, and a query model the team would need to learn. Both are third-party dependencies. The Neo4j option is more deeply integrated with GCP's operational model. The Neptune option has a worse operational profile for a GCP-native deployment. The "GCP-native purity" argument favours Spanner Graph, which is the documented re-evaluation candidate — not Neptune. This ADR does not choose Neo4j over a GCP-native option. It chooses the best available option given the current GA status of GCP's own graph product.
What an ADR reveals that a design document does not
Reading these three ADRs in sequence, a pattern becomes visible that is not visible in any other design artefact: the shape of the decision space at the time each choice was made. The rejected alternatives are not historical footnotes. They are the live risk register — the options that were available but not chosen, each of which might become the right answer if circumstances change.
ADR-002's rejection of Vertex AI Vector Search, for example, contains within it a specific trigger condition: 5 million chunks. When the corpus crosses that threshold, the ADR is not merely out of date — it contains, in the rejection rationale, the precise argument for why the original decision no longer applies. The migration path writes itself from the original ADR. This is the property that makes a well-written ADR more valuable than any amount of post-hoc documentation.
The rebuttal field reveals something different: the quality of the reasoning at the time of the decision. A rebuttal that engages a weak objection tells you the decision was not seriously challenged. A rebuttal that engages a strong objection and answers it with a specific, bounded argument tells you the decision was tested. The ADR-001 rebuttal on lock-in, for example, does not argue that lock-in is acceptable as a general principle. It argues that portability is only valuable if it applies to the full system, and that this system's other components preclude portability regardless of the orchestration framework choice. That is a specific argument. It can be falsified. If a future requirement changes the portability assumption, the rebuttal fails and the ADR must be revisited.
An ADR that does not engage the strongest objection is not an architectural record. It is a justification. The difference matters most precisely when circumstances change and you need to know whether the original decision was right for reasons that still apply, or right for reasons that no longer do.
The ADR as a hiring signal
There is a practical reason why ADRs matter to how architects are evaluated that goes beyond their value as design artefacts. In a system design interview, the questions that separate strong candidates from adequate ones are not "what would you build?" They are "what did you decide not to build, and why?" and "what's the strongest argument against your proposed design, and how do you answer it?"
These are ADR questions. They probe whether the candidate has actually tested their design decisions under adversarial conditions — whether they have sat with the best objection and produced a specific, bounded response — or whether they have simply arrived at a conclusion and looked for reasons to support it. The difference is audible in the answer. It is also visible in the design artefacts a candidate produces: an ADR with a strong rebuttal is evidence of the former. A design document with no rejected alternatives and no objections engaged is evidence of the latter.
The discipline of writing the rebuttal field — of finding the strongest objection and answering it honestly — is the discipline that makes a design decision trustworthy. Not because the answer is always right, but because the process of finding the strongest objection and testing the decision against it is the only way to know whether the decision is right for the right reasons, and whether those reasons will still hold when the system is operating under conditions its designers did not fully anticipate.
References & Further Reading
Nygard, M. (2011). "Documenting Architecture Decisions." Cognitect Blog. — The original article defining the ADR format: Context, Decision, Status, Consequences. The foundational reference for the structure described in this article. Available at thinkrelevance.com.
Keeling, M. (2017). Design It! From Programmer to Software Architect. Pragmatic Programmers. — Chapter 11 covers architectural decisions as first-class design artefacts. Keeling's framing of the decision as the unit of architectural thinking, not the diagram, is the grounding for this article's argument.
The Open Group, TOGAF 10 Standard — Architecture Decision Records are referenced throughout the ADM as evidence artefacts for Phase H Architecture Change Management reviews. The relationship between ADRs, the requirements register, and the risk register described in Figure 1 follows the TOGAF Phase H governance model.
Richards, M. and Ford, N. (2020). Fundamentals of Software Architecture. O'Reilly. — Chapter 19, "Making Architecture Decisions," provides the technical architect's perspective on documenting trade-offs. The emphasis on making decisions reversible where possible, and documenting the conditions under which reversal is appropriate, underlies the graduation trigger pattern in ADR-002.
Hohpe, G. (2020). The Software Architect Elevator. O'Reilly. — The distinction between decisions made at the penthouse level (strategy) and the engine room level (implementation), and why both must be documented, is the theoretical underpinning for why ADRs belong in a TOGAF Phase H governance gate and not just in a code repository.
These notes are published when there is something worth saying. To receive new Field Notes directly, write to hello@datadomine.com with the subject line: Field Notes.