AI Skill Report Card

Making Architecture Decisions

A91·Oct 15, 2026·Source: Extension-selection

Architecture decisions are consequential and hard to reverse. Never decide from memory or pattern-matching alone — inspect first, decide second, document third. The simplest architecture that satisfies verified requirements beats the most "scalable" one.

Activate when:

  • Starting structural design for a new project or new major subsystem
  • A requested change affects module boundaries, data flow, service topology, or dependency direction
  • Choosing between competing approaches (e.g., monolith vs. services, sync vs. async, SQL vs. NoSQL, REST vs. events)
  • Planning a migration, large refactor, or framework/platform change
  • Existing architecture docs look stale or contradict the code
  • Someone asks "how should this be structured?" or "what's the right pattern here?"

Do NOT activate for:

  • Implementing a feature within established boundaries
  • Isolated bug fixes, typo fixes, styling, copy changes
  • Writing tests for existing behavior
  • Performance tuning of a single function/query (unless it reveals a structural flaw)

When in doubt: if the change can be described as "add/fix this one thing" without touching boundaries or contracts, it's implementation, not architecture.

This skill decides structure and contracts, not implementation detail.

SpecialistHandoff
FrontendThis skill defines component/module boundaries and API contracts the UI consumes; frontend specialist owns UI implementation, state management detail, styling.
BackendThis skill defines service boundaries, data flow, and interfaces; backend specialist owns endpoint implementation, business logic, ORM/query code.
DebuggingIf debugging reveals a structural root cause (e.g., leaky abstraction, wrong boundary), hand off here to decide the fix's architecture; routine bug diagnosis stays with debugging.
SecurityFlag security-relevant trade-offs (trust boundaries, auth placement) but defer deep threat modeling and vulnerability analysis to the security specialist.
PerformanceUse quality attribute scenarios to set performance requirements/targets; defer profiling and micro-optimization to the performance specialist.
Technical researchDelegate open technology comparisons needing external/current data (e.g., "which vendor/library is best right now") to research, then consume findings as evidence.
TestingDefine testability boundaries and what needs contract/integration tests; defer test case design and execution to the testing specialist.
15 / 15
Progress:
- [ ] 1. Inspect reality (existing code, docs, deps, interfaces)
- [ ] 2. Establish requirements, quality attributes, constraints, acceptance criteria
- [ ] 3. Generate realistic alternatives
- [ ] 4. Compare trade-offs explicitly
- [ ] 5. Choose simplest sufficient option
- [ ] 6. Define boundaries, contracts, data flow
- [ ] 7. Document decision (ADR / C4 update) if significant
- [ ] 8. Hand off actionable spec to implementation specialists

Step 1: Inspect Reality (never trust memory)

For existing projects, before proposing anything:

  • Read actual directory structure, not an assumed one
  • Open key source files for the area under discussion — don't infer behavior from filenames or prior conversation
  • Check actual dependency manifests (package.json, pom.xml, requirements.txt, go.mod, etc.) for real versions and what's actually used vs. declared
  • Check config files (env, CI/CD, IaC) for deployment topology truth
  • Read existing architecture docs/diagrams/ADRs — then verify against code; flag contradictions explicitly rather than trusting the doc
  • Identify existing module boundaries and current dependency direction (what depends on what)

For new projects, inspect instead:

  • Any existing scaffolding, chosen stack constraints, team conventions
  • Stated business/product constraints (deadline, team size, compliance)

Never propose structural changes based on what you "recall" the codebase looking like — re-read it.

Step 2: Establish Requirements Before Deciding

Do not pick an architecture until you can state:

  1. Functional requirements — what must the system do (specific, not "handle users")
  2. Quality attributes — expressed as testable scenarios, e.g.:

    "Under 500 concurrent users, 95th percentile checkout latency < 300ms" "System must survive single AZ failure with < 1 min downtime" Not vague goals like "fast" or "scalable."

  3. Constraints — team size/skills, budget, timeline, existing stack, compliance/regulatory, hosting limits
  4. Acceptance criteria — how we'll know the decision succeeded

If these are missing or vague, ask or state explicit assumptions — do not invent plausible-sounding requirements and proceed as if they were given. Label anything not explicitly confirmed as ASSUMPTION.

If a requirement is unclear but not consequential (low cost to change later), proceed with a stated assumption rather than blocking. If it's consequential (hard/costly to reverse), surface the uncertainty and seek confirmation before committing.

Step 3: Generate Realistic Alternatives

Produce 2–3 genuinely viable options, not a strawman + the preferred answer. Include "do nothing structural / smallest change" as a baseline option when applicable. Ground options in what's evidenced (Step 1), not in generic best-practice lists.

Step 4: Compare Trade-offs Explicitly

For each alternative, address what's relevant to the decision (not every axis every time):

  • Maintainability — cognitive load, coupling, how changes ripple
  • Performance — against the quality attribute scenarios from Step 2
  • Reliability — failure modes, blast radius, recovery
  • Security — trust boundaries, attack surface changes
  • Operational complexity — deployment, monitoring, on-call burden, new moving parts
  • Cost — infra, licensing, engineering time
  • Migration risk — if changing existing systems: data migration, downtime, rollback path, blast radius if wrong

Use a short trade-off table when 2+ alternatives are being seriously compared. Skip formal analysis for low-stakes, easily reversible decisions.

Step 5: Choose the Simplest Sufficient Option

Default to the option that satisfies Step 2's requirements with the least structural complexity. Reject additions justified only by:

  • "It's a best practice" (without a tied requirement)
  • "We might need it later" (speculative future-proofing)
  • "It's more scalable" (when no scale requirement demands it)
  • Familiarity/popularity of a framework without fit justification

Explicitly name what you are not adding and why (e.g., "No message queue: no requirement for async decoupling or burst absorption exists today").

Step 6: Define Boundaries and Contracts

When the decision involves structure, specify concretely:

  • Component/module responsibilities (one sentence each, non-overlapping)
  • Dependency direction (who may depend on whom; what's forbidden)
  • Data flow (what moves where, sync vs async, ownership of data)
  • Interfaces/API contracts (inputs, outputs, error semantics) — enough that an implementation specialist doesn't have to invent them

This is the deliverable implementation specialists consume. Be concrete: name modules, not placeholders like "service layer handles stuff."

Step 7: Document When Justified

Match documentation effort to decision significance:

  • Trivial/reversible → no formal doc, just explain reasoning inline
  • Moderate → a short ADR (see format below)
  • Significant (new service boundary, data model change, platform shift) → ADR + update/create a C4 diagram (Context/Container level usually sufficient; Component level only if genuinely useful) + update architecture map

ADR format:

Markdown
# ADR-NNN: <decision title>
Recommendation▾
Add a brief Quick Start section at the top with an immediate actionable checklist or one-liner before the deep workflow dive, since currently useful content starts only after several conceptual sections

Proposed | Accepted | Superseded by ADR-XXX

What requirement/problem forced this decision. Key constraints. Evidence inspected.

What we chose, stated plainly.

  • Option A — rejected because...
  • Option B — rejected because...

What becomes easier, harder, or risky as a result. Follow-up work created.


Store ADRs in `docs/adr/` (or project convention if one exists — check first). Update existing architecture docs rather than leaving contradictions for future readers; note what changed and why.

### Step 8: Produce Actionable Output

Final output to implementation specialists must include:
- The decision and its rationale (brief)
- Concrete boundaries/contracts from Step 6
- Explicit non-goals ("do not add X")
- Open risks/uncertainties still unresolved, flagged as such

Do not leave gaps for implementers to fill with invented requirements — if something is genuinely undecided, say so rather than letting it be silently assumed.
  • C4 Model — for communicating system structure at Context/Container/Component levels. Use Context+Container for most decisions; Component level only for complex internals worth mapping.
  • ADRs — for recording why, not just what. Use for any decision that's hard to reverse or non-obvious in hindsight.
  • Quality attribute scenarios — turn vague "-ilities" into testable statements (stimulus, environment, response, measure).
  • Dependency analysis — trace actual import/call graphs before claiming a boundary is clean or dirty; don't assume from folder names.
  • Trade-off/decision matrices — for 2+ seriously competing alternatives with multiple relevant quality attributes.

Pick what the decision needs. A one-line config change doesn't need a C4 diagram; a new service boundary probably needs an ADR at minimum.

17 / 20

Example 1 — Existing project, proposed change Input: "Should we split the monolith into microservices to scale better?" Output:

  • Inspect: read actual codebase, find it's a Django monolith, 12k LOC, one Postgres DB, deployed as a single container, current traffic ~50 req/s peak.
  • Requirements check: ask/confirm what "scale better" means — turns out it's deploy frequency pain (one team blocked by another's release), not request volume.
  • Alternatives: (a) do nothing structural, improve CI/CD and feature flags; (b) modularize within the monolith (clear internal boundaries, enforce via lint rules); (c) extract 1 high-churn module into a service.
  • Trade-offs: microservices add operational complexity (new deploy pipelines, service discovery, distributed debugging) not justified by current scale; real pain is release coupling.
  • Decision: Option (b) — modularize internally first; revisit service extraction only if a specific module's team-ownership/deploy-cadence conflict remains after that. ADR written; no C4 container diagram change yet (still one deployable unit), but component-level module map added.
  • Explicit non-goal: "Not introducing Kubernetes/service mesh — no evidence of need."

Example 2 — New project Input: "We're building a new internal tool for 20 users to track equipment maintenance." Output:

  • Requirements: CRUD app, 20 users, low traffic, team of 2 devs, 6
Recommendation▾
The second example is cut off mid-sentence ('team of 2 devs, 6') — ensure the skill file is complete and both examples fully resolved with concrete outputs
0
Grade AAI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
11/15
Workflow
15/15
Examples
17/20
Completeness
20/20
Format
15/15
Conciseness
13/15