Author and maintain Architecture Decision Records (ADRs) for Salesforce implementations: capture chosen approach, rejected alternatives, constraints, and consequences. Trigger keywords: adr, architecture decision record, design decision log, technical decision. NOT for making the design decision itself, e.g. Flow vs Apex — use architect/solution-design-patterns. NOT for a formal architecture review that produces findings — use architect/well-architected-review.
An ADR's real product is not the decision. It is the recorded premise — the
volumes, limits, and requirements the decision depended on. That is what lets a
future team test whether the choice still holds rather than re-litigating it,
and it is the part most ADRs omit.
On Salesforce specifically, two things make ADR discipline harder than
elsewhere: three major releases a year expire premises fast, and the platform's
lifecycle churn (product end-of-sale, feature retirement, GA dates) invites
confident unsourced claims into a document that is deliberately never updated.
ADR Candidacy
Promote a decision to ADR when any of these holds:
Multi-quarter impact — platform choice (Flow vs Apex vs Agentforce),
pattern adoption (Trigger Handler, Selector Layer), org topology (single-org
vs multi-org), integration approach, sharing model, licensing posture.
Reversal of an earlier recorded choice — always a new ADR that supersedes;
never a deletion, never an edit.
The 6-month test — a joiner will ask "why did we do this?" and needs a
document to read.
Out of scope:
Applying an existing ADR to a new object or class. That is a line in the
PR description — "Follows ADR-0003 (TriggerHandler framework)."
Task-level tradeoffs.
Anything fully internal to one feature's lifecycle.
The test: if it fits in a PR description, it is not an ADR.
The corollary, which is more useful: if you cannot name two alternatives a
competent person could actually have chosen, the decision was not open — you are
documenting a standard, not deciding.
ADRs And Decision Trees Are Different Layers
This repository has standards/decision-trees/. An ADR that re-derives one of
those trees is a fork waiting to diverge — and the first tree update makes them
contradict each other.
Decision tree
ADR
Scope
organisation-wide routing rule
one situation
Answers
"which technology for this shape of problem?"
"which branch applied here, and what was true?"
Lifecycle
updated as the platform changes
frozen on acceptance
When a tree routes the decision, the ADR records the branch and the
inputs, not the reasoning:
## Decision Trees Consulted
- `automation-selection.md` — Q1 (scheduled clock) → Q10 (>50k records) → Batch Apex
- `async-selection.md` — Q9 (needs ad hoc re-run) → Schedulable wrapper
Inputs at the time of this decision:
- 1.9M Account rows today; ~3.4M projected after the Q3 acquisition
- Business requirement: accurate by 07:00 daily
Two cases still need an ADR even when a tree answered:
You are deviating from the tree. Record the branch, why this situation is
the exception, and what would end the exception. A deviation with no ADR is
indistinguishable from an error.
The tree does not cover the scenario. Write the ADR, and raise the gap so
the tree can be extended — do not force-fit.
And the inverse: when the same decision recurs identically across teams, it
belongs in the tree, not in a fourth ADR.
Required Sections
Standard Nygard structure, one file per decision in docs/adr/:
Title — ADR-XXXX: <one-line decision>
Status — Proposed / Accepted / Rejected / Superseded by ADR-YYYY (with date)
Context — the forces, the constraints, and the inputs the decision depended on
Decision — the choice, in the active voice
Consequences — positive and at least one specific, checkable negative
Alternatives Considered — at least two that a competent person could have chosen
Date — the decision date, ISO-8601, never updated
Deciders — named people with the role they held at the time, plus the forum
Plus, on Salesforce:
Decision Trees Consulted — branch and question numbers, or an explicit "no tree covers this"
Review Trigger — where the decision rests on a current platform limitation rather than a principle, with a named owner
Sourcing Platform Claims
An ADR is the worst possible place for an unsourced lifecycle date, because
ADRs are deliberately not updated. A wrong date in a design doc is corrected
next sprint; a wrong date in an ADR stays load-bearing forever.
Every lifecycle, retirement, GA, or limit claim needs one of:
a Salesforce-hosted URL, or
a named person and the date they confirmed it.
Consultancy blogs are not sources for an architecture record. Where a claim
cannot be verified, mark it inline rather than laundering it:
<!-- UNVERIFIED: a specific end-of-sale date of 27 March 2025 circulates
widely in consultancy writing. Not confirmed from a Salesforce source. -->
The same applies to managed-package constraints: record the package name, the
version tested, and how the constraint was established, so a future reader
can re-test it instead of assuming it still holds.
Recommended Workflow
Apply the candidacy test. If it fits in a PR description, or you cannot name
two viable alternatives, stop — this is not an ADR.
Check standards/decision-trees/ before writing. If a tree routes this,
record the branch and the inputs rather than re-deriving the reasoning. If
you are deviating from the tree, say so explicitly and name what would end
the exception.
Draft from templates/adr-template.md (Status = Proposed only if a real
review forum exists; otherwise write it Accepted and retrospective), and
source every platform claim as you go — Salesforce URL, or a named person
and date. Mark anything unverifiable inline. Record package name, version
tested, and method for package-attributed constraints.
Force the negatives. Ask what the team writing the superseding ADR will
complain about, and write that down. If nothing comes to mind, this was not
a tradeoff.
Add a Review Trigger with a named owner wherever the decision rests on a
current platform limitation or on a pending vendor decision. A calendar date
is not a trigger — a condition is.
Mark Accepted with the date and named deciders, update docs/adr/INDEX.md
including the open review triggers table, and cite the ADR number in
subsequent PR descriptions.
On supersession: write a new ADR, flip the old one's Status line and nothing
else, link both ways, and state whether a premise expired or a mistake
was found — they teach different lessons.
Review Checklist
Passes the candidacy test; two genuinely viable alternatives exist
Decision trees checked; branch cited, or "no tree covers this" stated
Deviation from a tree, if any, is explicit with an end condition
Context records the inputs (volumes, limits, requirements), not just narrative
Every platform lifecycle claim has a Salesforce URL or a named confirmer + date
Unverifiable claims marked inline, not asserted
Managed-package constraints carry package name, version tested, and method
At least one specific, checkable negative consequence
Review Trigger present where the decision rests on a current limitation, with an owner
Deciders are named people with roles held at the time
Date is the decision date and has never been updated
Global four-digit numbering, one directory, in the repo the decision governs
INDEX.md updated, including the open-triggers table
Supersession links resolve both ways; the superseded body is untouched
Fits on roughly one page; the design doc is linked, not inlined
Worked Examples (see references/examples.md)
A decision the tree already answers — record the branch, not the reasoning
A sharing model decision — where the ordering is the decision
A platform lifecycle decision — deciding to wait, with named triggers
Supersession done properly — a premise expiring, not a mistake
A decision that should not have been an ADR — and where it belongs instead
The index — including the open-review-triggers table
Common Gotchas (see references/gotchas.md)
An ADR that re-derives a decision tree is a fork waiting to diverge
Three releases a year expire ADR premises faster than most platforms
"Decide to wait" is a decision, and the one nobody writes down
A named managed-package constraint is a fact with a version number
Org strategy ADRs need the licensing consequence, not just the topology
Never edit the body of a superseded ADR
Proposed ADRs rot silently
Top LLM Anti-Patterns (full list in references/llm-anti-patterns.md)
Re-deriving a decision tree inside the ADR
Alternatives Considered populated with strawmen
Consequences that are all positive
Editing the superseded ADR instead of superseding it
An ADR for every decision
An ADR as a design specification
Stating platform lifecycle facts without sourcing or dating them
"Decide to wait" left unwritten, or written without triggers
Related
architect/solution-design-patterns — for making the decision. This skill
is for recording it.
architect/well-architected-review — a review that produces findings, which
is a different artifact with a different lifecycle.
standards/decision-trees/README.md — the layer above ADRs. Read the
relevant tree before writing an ADR about a technology choice.
Official Sources Used
See references/well-architected.md for the full source list, including an
explicit caveat on the CPQ lifecycle claims used in the worked examples.
1---2name: architecture-decision-records3description: Author and maintain Architecture Decision Records (ADRs) for Salesforce implementations: capture chosen approach, rejected alternatives, constraints, and consequences. Trigger keywords: adr, architecture decision record, design decision log, technical decision. NOT for making the design decision itself, e.g. Flow vs Apex — use architect/solution-design-patterns. NOT for a formal architecture review that produces findings — use architect/well-architected-review.4---56# Architecture Decision Records78An ADR's real product is not the decision. It is the recorded **premise** — the9volumes, limits, and requirements the decision depended on. That is what lets a10future team test whether the choice still holds rather than re-litigating it,11and it is the part most ADRs omit.1213On Salesforce specifically, two things make ADR discipline harder than14elsewhere: three major releases a year expire premises fast, and the platform's15lifecycle churn (product end-of-sale, feature retirement, GA dates) invites16confident unsourced claims into a document that is deliberately never updated.1718---1920## ADR Candidacy2122Promote a decision to ADR when **any** of these holds:2324- **Multi-quarter impact** — platform choice (Flow vs Apex vs Agentforce),25 pattern adoption (Trigger Handler, Selector Layer), org topology (single-org26 vs multi-org), integration approach, sharing model, licensing posture.27- **Reversal of an earlier recorded choice** — always a new ADR that supersedes;28 never a deletion, never an edit.29- **The 6-month test** — a joiner will ask "why did we do this?" and needs a30 document to read.3132Out of scope:3334- Applying an **existing** ADR to a new object or class. That is a line in the35 PR description — `"Follows ADR-0003 (TriggerHandler framework)."`36- Task-level tradeoffs.37- Anything fully internal to one feature's lifecycle.3839**The test:** if it fits in a PR description, it is not an ADR.40**The corollary, which is more useful:** if you cannot name two alternatives a41competent person could actually have chosen, the decision was not open — you are42documenting a standard, not deciding.4344---4546## ADRs And Decision Trees Are Different Layers4748This repository has `standards/decision-trees/`. An ADR that re-derives one of49those trees is a fork waiting to diverge — and the first tree update makes them50contradict each other.5152| | Decision tree | ADR |53|---|---|---|54| Scope | organisation-wide routing rule | one situation |55| Answers | "which technology for this *shape* of problem?" | "which branch applied *here*, and what was true?" |56| Lifecycle | updated as the platform changes | frozen on acceptance |5758When a tree routes the decision, the ADR records the **branch** and the59**inputs**, not the reasoning:6061```markdown62## Decision Trees Consulted63- `automation-selection.md` — Q1 (scheduled clock) → Q10 (>50k records) → Batch Apex64- `async-selection.md` — Q9 (needs ad hoc re-run) → Schedulable wrapper6566Inputs at the time of this decision:67- 1.9M Account rows today; ~3.4M projected after the Q3 acquisition68- Business requirement: accurate by 07:00 daily69```7071Two cases still need an ADR even when a tree answered:72731. **You are deviating from the tree.** Record the branch, why this situation is74 the exception, and what would end the exception. A deviation with no ADR is75 indistinguishable from an error.762. **The tree does not cover the scenario.** Write the ADR, and raise the gap so77 the tree can be extended — do not force-fit.7879And the inverse: when the same decision recurs identically across teams, it80belongs in the *tree*, not in a fourth ADR.8182---8384## Required Sections8586Standard Nygard structure, one file per decision in `docs/adr/`:87881. **Title** — `ADR-XXXX: <one-line decision>`892. **Status** — Proposed / Accepted / Rejected / Superseded by ADR-YYYY (with date)903. **Context** — the forces, the constraints, and the **inputs** the decision depended on914. **Decision** — the choice, in the active voice925. **Consequences** — positive **and** at least one specific, checkable negative936. **Alternatives Considered** — at least two that a competent person could have chosen947. **Date** — the decision date, ISO-8601, never updated958. **Deciders** — named people with the role they held at the time, plus the forum9697Plus, on Salesforce:98999. **Decision Trees Consulted** — branch and question numbers, or an explicit "no tree covers this"10010. **Review Trigger** — where the decision rests on a *current platform limitation* rather than a principle, with a named owner101102---103104## Sourcing Platform Claims105106An ADR is the worst possible place for an unsourced lifecycle date, because107ADRs are deliberately not updated. A wrong date in a design doc is corrected108next sprint; a wrong date in an ADR stays load-bearing forever.109110Every lifecycle, retirement, GA, or limit claim needs one of:111112- a **Salesforce-hosted URL**, or113- a **named person and the date they confirmed it**.114115Consultancy blogs are not sources for an architecture record. Where a claim116cannot be verified, mark it inline rather than laundering it:117118```markdown119<!-- UNVERIFIED: a specific end-of-sale date of 27 March 2025 circulates120widely in consultancy writing. Not confirmed from a Salesforce source. -->121```122123The same applies to managed-package constraints: record the package name, the124**version tested**, and *how* the constraint was established, so a future reader125can re-test it instead of assuming it still holds.126127---128129## Recommended Workflow1301311. Apply the candidacy test. If it fits in a PR description, or you cannot name132 two viable alternatives, stop — this is not an ADR.1332. Check `standards/decision-trees/` before writing. If a tree routes this,134 record the branch and the inputs rather than re-deriving the reasoning. If135 you are deviating from the tree, say so explicitly and name what would end136 the exception.1373. Draft from `templates/adr-template.md` (Status = Proposed only if a real138 review forum exists; otherwise write it Accepted and retrospective), and139 source every platform claim as you go — Salesforce URL, or a named person140 and date. Mark anything unverifiable inline. Record package name, version141 tested, and method for package-attributed constraints.1424. Force the negatives. Ask what the team writing the superseding ADR will143 complain about, and write that down. If nothing comes to mind, this was not144 a tradeoff.1455. Add a **Review Trigger** with a named owner wherever the decision rests on a146 current platform limitation or on a pending vendor decision. A calendar date147 is not a trigger — a condition is.1486. Mark Accepted with the date and named deciders, update `docs/adr/INDEX.md`149 including the **open review triggers** table, and cite the ADR number in150 subsequent PR descriptions.1517. On supersession: write a new ADR, flip the old one's Status line and nothing152 else, link both ways, and state whether a premise **expired** or a mistake153 was **found** — they teach different lessons.154155---156157## Review Checklist158159- [ ] Passes the candidacy test; two genuinely viable alternatives exist160- [ ] Decision trees checked; branch cited, or "no tree covers this" stated161- [ ] Deviation from a tree, if any, is explicit with an end condition162- [ ] Context records the **inputs** (volumes, limits, requirements), not just narrative163- [ ] Every platform lifecycle claim has a Salesforce URL or a named confirmer + date164- [ ] Unverifiable claims marked inline, not asserted165- [ ] Managed-package constraints carry package name, version tested, and method166- [ ] At least one specific, checkable negative consequence167- [ ] Review Trigger present where the decision rests on a current limitation, with an owner168- [ ] Deciders are named people with roles held at the time169- [ ] Date is the decision date and has never been updated170- [ ] Global four-digit numbering, one directory, in the repo the decision governs171- [ ] `INDEX.md` updated, including the open-triggers table172- [ ] Supersession links resolve both ways; the superseded body is untouched173- [ ] Fits on roughly one page; the design doc is linked, not inlined174175---176177## Worked Examples (see `references/examples.md`)178179- *A decision the tree already answers* — record the branch, not the reasoning180- *A sharing model decision* — where the ordering **is** the decision181- *A platform lifecycle decision* — deciding to wait, with named triggers182- *Supersession done properly* — a premise expiring, not a mistake183- *A decision that should not have been an ADR* — and where it belongs instead184- *The index* — including the open-review-triggers table185186## Common Gotchas (see `references/gotchas.md`)187188- An ADR that re-derives a decision tree is a fork waiting to diverge189- Three releases a year expire ADR premises faster than most platforms190- "Decide to wait" is a decision, and the one nobody writes down191- A named managed-package constraint is a fact with a version number192- Org strategy ADRs need the licensing consequence, not just the topology193- Never edit the body of a superseded ADR194- Proposed ADRs rot silently195196## Top LLM Anti-Patterns (full list in `references/llm-anti-patterns.md`)197198- Re-deriving a decision tree inside the ADR199- Alternatives Considered populated with strawmen200- Consequences that are all positive201- Editing the superseded ADR instead of superseding it202- An ADR for every decision203- An ADR as a design specification204- Stating platform lifecycle facts without sourcing or dating them205- "Decide to wait" left unwritten, or written without triggers206207---208209## Related210211- **architect/solution-design-patterns** — for making the decision. This skill212 is for recording it.213- **architect/well-architected-review** — a review that produces findings, which214 is a different artifact with a different lifecycle.215- **standards/decision-trees/README.md** — the layer above ADRs. Read the216 relevant tree before writing an ADR about a technology choice.217218## Official Sources Used219220See `references/well-architected.md` for the full source list, including an221explicit caveat on the CPQ lifecycle claims used in the worked examples.
Run npx skillmds add pranavnagrecha/architecture-decision-records in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Author and maintain Architecture Decision Records (ADRs) for Salesforce implementations: capture chosen approach, rejected alternatives, constraints, and consequences. Trigger keywords: adr, architecture decision record, design decision log, technical decision. NOT for making the design decision itself, e.g. Flow vs Apex — use architect/solution-design-patterns. NOT for a formal architecture review that produces findings — use architect/well-architected-review. It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Capability flags: executes scripts. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
PranavNagrecha (@pranavnagrecha) published this skill. Their other Agent Skills are listed on their SkillMD profile.