Foundations · For Architects, engineering leaders, security architects
Architecture decision records for security
Security decisions outlive the people who made them. A practical ADR template with security fields, a worked example, and how to keep decisions honest against the system you actually run.
4 min read5 sources
Every architecture contains security decisions. The only question is whether anyone can find out why they were made.
Decisions outlive the people who made them
Two years after launch, a new engineer finds that the export service runs in its own cloud account with a separate deployment pipeline. It looks like accidental complexity, so they propose merging it into the main account. Nobody on the current team remembers that the separation was the condition under which a large customer agreed to bulk exports of their data.
Architecture decision records exist for this moment. An ADR is a short document that captures one significant decision: the context, the decision, the alternatives and the consequences. Michael Nygard's original proposal was deliberately lightweight, and that is its strength. ADRs are written while the decision is being made, kept next to the code, and never rewritten; a changed decision gets a new record that supersedes the old one.
Security gains more from ADRs than most disciplines, because so many security properties are absences: a path that does not exist, a permission that was not granted, a data flow that was refused. Absences leave no trace in the code. Only the record explains them.
What a security-aware ADR records
The standard sections work; add a few that make the security reasoning explicit.
# ADR-0042: Run bulk exports in a separate cloud account
Status: Accepted (2026-03-14)
Deciders: Platform lead, security architect, product owner
## Context
Enterprise customers can request a full export of their data.
Exports read every table for one tenant and write to a bucket
the customer downloads from.
## Decision
Exports run in a dedicated account with its own pipeline and a
read-only, per-tenant database role. The export bucket lives only
in that account.
## Security considerations
- Assets: complete tenant datasets (confidential).
- Boundaries affected: tenant, administrative domain, data zone.
- Threats considered: a compromised export job reading other
tenants; export links leaking; production credentials reaching
the export bucket.
- Controls: per-tenant role issued per job; links expire after
24 hours; no production identity can write to the account.
## Alternatives
- Exports inside the main account (rejected: one compromise
reaches every tenant's full dataset).
## Consequences
- A second pipeline to maintain.
- Residual risk: an export link forwarded by the customer.
Accepted by the product owner until 2027-03-14.
## Revisit when
- Exports start including files from object storage.
- The per-tenant role design changes.Three fields carry most of the security value. Boundaries affected ties the decision to the trust boundaries it creates or changes. Residual risk, accepted by whom, until when makes risk acceptance explicit and temporary. Revisit when names the facts that would make the decision wrong, so it can be reopened for a reason rather than forgotten.
Make decisions part of the change process
ADRs work when they are part of how change happens, not a parallel documentation effort. A simple loop is enough:
Define the triggers once, so engineers know when an ADR is expected: a new entry point, a new kind of identity or a widened role, a new flow of confidential data, a new third-party dependency with network access, a new path to production, or an accepted risk. Most changes need none of this; the ones that do are exactly the ones a future reader will ask about.
Read the diagram as text
- Propose: Change proposed, ADR drafted
- Decide: Security review, Accepted
- Live with it: Implemented, Revisit trigger, New ADR
- Change proposed → ADR drafted: touches a boundary
- ADR drafted → Security review: options
- Security review → Accepted: decision
- Accepted → Implemented: build
- Implemented → Revisit trigger: drift found
- Revisit trigger → New ADR: reopen
- New ADR → ADR drafted: links back
Store them where the system lives
Keep ADRs in the repository, numbered and in plain text, so they are reviewed in the same pull requests as the code they describe and found by the same search. Link each record to the components it concerns. When the architecture model of a system can point to the decision behind a boundary, review conversations change from "why is this here?" to "is the reason still true?".
Use ADRs to accept risk properly
Risk acceptance is a security decision like any other, and it deserves the same record. An accepted risk should name the hypothesis it answers, the evidence considered, the compensating controls, the person who accepted it and the date it expires. Expiry is the important part: it turns "we will live with this" into "we will look at this again on a known date", and it stops temporary exceptions from becoming permanent architecture without anyone deciding so.
Mistakes that make ADRs useless
A few habits turn a decision log into noise. Avoid them:
- Recording the decision without the alternatives. A reader cannot judge whether the reasoning still holds if they cannot see what was rejected and why.
- Editing accepted records. Once accepted, an ADR is history. Change the decision with a new record that supersedes it, so the trail stays intact.
- Writing them after the fact. A record written to justify something already built tends to leave out the trade-offs that were actually argued over.
- Leaving security to a separate document. If the security reasoning lives elsewhere, it will not be read when the decision is revisited.
- Recording everything. If every library upgrade gets an ADR, the important ones disappear. Use the triggers above.
Keep decisions honest against the running system
A decision is only as good as its implementation, and implementations drift. A later change can quietly reintroduce the path an ADR ruled out, widen the role it scoped, or move the data it isolated. Periodically compare what the records say the system should be with what the evidence shows it is. Where they differ, either the system has drifted and needs fixing, or the world has changed and the decision needs a new record.
Sources
- Documenting Architecture Decisions
Michael Nygard, 2011
- Architectural Decision Records
ADR GitHub organization
- ADR process
AWS Prescriptive Guidance
- Maintain an architecture decision record
Microsoft Azure Well-Architected Framework
- Engineering Trustworthy Secure Systems (SP 800-160 Vol. 1 Rev. 1)
NIST