← Back to blog

    Architecture Decision Records (ADRs): the simplest way to stop repeating the same debates

    Documentation

    Startups don’t usually lack engineering effort.

    They lack decision clarity.

    A few months in, the same questions start looping:

    • “Why did we choose DynamoDB again?”
    • “Was this service boundary intentional or accidental?”
    • “Why are we publishing events and doing synchronous calls?”
    • “Who approved this and what were the constraints at the time?”

    When the decision isn’t written down, the team relies on oral history. The original context fades, new people join, constraints change, and debates become expensive.

    That’s where Architecture Decision Records (ADRs) help.

    ADRs are not a fancy framework. They’re just a lightweight way to document high-impact decisions so you can:

    • move faster (less re-debate)
    • onboard better (less tribal knowledge)
    • reduce risk (trade-offs made explicit)
    • keep architecture intentional (not accidental)

    This post is a practical guide to using ADRs without turning your team into a paperwork factory.


    What is an ADR?

    An ADR is a short document that captures:

    1. Context — what problem are we solving and why now?
    2. Options considered — what did we evaluate?
    3. Decision — what are we choosing?
    4. Rationale — why this option, given constraints?
    5. Consequences — what trade-offs are we accepting?
    6. Rollout plan + signals — how we’ll implement and validate

    Think of it as a time capsule for your future team.

    ADRs are especially valuable when decisions are:

    • hard to reverse (data model, multi-tenancy, infra choices)
    • cross-cutting (affects multiple teams)
    • risky (reliability / security / compliance)
    • politically charged (trade-offs between speed and correctness)

    Why ADRs matter (even when you “just need to ship”)

    Most teams don’t feel the cost of missing ADRs immediately.

    They feel it later as:

    • rework (“we picked the wrong boundary”)
    • slow onboarding (“nobody knows why”)
    • decision churn (“we keep revisiting the same choice”)
    • operational pain (“we didn’t anticipate the failure modes”)

    The irony: teams avoid writing ADRs to “save time”, and then spend far more time in repeated debate and corrective work.

    A good ADR is typically 30–90 minutes of work.

    That’s cheaper than one day of:

    • multi-team Slack threads
    • half-baked migrations
    • incident postmortems that conclude “we should’ve anticipated this”

    What an ADR is not

    Let’s kill the common misconceptions:

    • Not a design doc. Design docs can be long. ADRs should be short.
    • Not a perfect record. It’s okay if it’s incomplete—capture what matters.
    • Not bureaucracy. If it doesn’t reduce rework or risk, don’t do it.
    • Not only for architects. Engineers closest to the work should write them.

    ADRs are about decision-making, not architectural cosplay.


    When should you write an ADR?

    Use ADRs for decisions that are high leverage or hard to undo.

    A simple trigger list:

    • Introducing a new datastore or changing the source of truth
    • Picking sync vs async across services
    • Defining service boundaries / splitting a monolith
    • Introducing multi-tenancy (tenant isolation model)
    • Choosing an auth model (multi-tenant auth, RBAC)
    • Deciding on a caching strategy that affects correctness
    • Making a reliability stance (SLOs, retry policy, DLQs)

    If the decision can be reversed in a day with minimal collateral damage, you probably don’t need an ADR.


    What a good ADR looks like (structure you can copy)

    A practical ADR template:

    • Status: Proposed | Accepted | Rejected | Superseded
    • Context: current situation + trigger + constraints
    • Options: 2–4 realistic choices (not strawmen)
    • Decision + rationale: tie back to constraints
    • Consequences: explicit trade-offs
    • Rollout plan: migration/compatibility/rollback
    • Metrics: what will we watch?
    • Links: PRs, dashboards, RFCs

    Two tips that keep ADRs high-signal:

    1. Write constraints first. The correct decision depends on what you can’t compromise.

    2. Make consequences explicit. Every option has a cost—name it.


    Examples (the kind of decisions ADRs de-risk)

    Here are three common ADR categories I see in funded startups:

    1) Database choice (Postgres vs DynamoDB vs “keep the current mess”)

    You’re usually deciding between:

    • iteration speed (schema evolution + querying)
    • operational complexity
    • correctness constraints
    • future scale assumptions

    Most teams get stuck arguing about scale prematurely. ADRs force you to write: what do we need now, what can we defer, and what are the escape hatches?

    2) Eventing vs synchronous calls

    Event-driven systems can improve resilience and decouple teams. But they also introduce eventual consistency, idempotency needs, and new failure modes.

    An ADR helps you answer:

    • which flows must be strongly consistent at request time?
    • where is eventual consistency acceptable (and what UI messaging is needed)?
    • what observability + DLQ strategy is required?

    3) Multi-tenancy model

    This is a classic “hard-to-undo” choice:

    • DB-per-tenant vs schema-per-tenant vs shared DB with tenant scoping

    The right answer depends on:

    • team size and ops capacity
    • compliance and customer needs
    • onboarding scale and cost sensitivity

    Write the constraints, pick a model, and document the guardrails (tests, RLS, scoping enforcement, query linting).


    How to operationalize ADRs (without process bloat)

    A lightweight operating model:

    1. Store ADRs in the repo: /docs/adrs/ (or a central engineering docs repo)
    2. Number them: 0001-..., 0002-... (easy references)
    3. PR requirement for certain changes:
      • “New datastore” → ADR required
      • “Cross-service contract change” → ADR required
    4. Keep them short: 1–2 pages is plenty
    5. Review like code: comments should focus on constraints, risks, and consequences

    If you do this consistently, ADRs become a muscle.


    Common mistakes

    • Writing ADRs too late (after implementation): the decision is already made.
    • Using ADRs for everything: you’ll train the team to ignore them.
    • Making options unrealistic: don’t include strawman options.
    • Skipping rollout/rollback: high-impact decisions need an exit plan.

    Want a ready-to-use ADR Pack?

    I put together an ADR pack with a template and three examples (DB choice, eventing vs sync, multi-tenancy).

    If you reply with your context (stage, team size, stack, and the decision you’re stuck on), I’ll point you to the highest-leverage way to use ADRs in your org.

    Enjoyed this? Give it a clap.