Software architecture
Prompting for application architecture: how a codebase is split into modules, layers and services, which patterns fit, how decisions are weighed, recorded and checked. Written for someone who can read code but hasn't designed a system before, or who manages people who do. The concepts themselves are in Software architecture and diagram notation in ERD & UML diagrams; distributed-systems concerns (scale, storage, failure) are in System design; the method behind every prompt here is in Prompting fundamentals.
How experts think
Architects start from the forces acting on the system, not from patterns. "Everything in software architecture is a trade-off" is the first law in Richards and Ford's Fundamentals of Software Architecture: a choice that improves one quality makes another worse, and the job is to choose which, on purpose. The questions an architect runs through before drawing anything:
| Question | Why it matters | Ask the model |
|---|---|---|
| What are the drivers? Business goals, key use cases, quality attributes, constraints | architecture exists to satisfy these; anything that serves none is decoration | "List the architecture drivers you can infer from my brief and ask about the gaps." |
| Which 3 qualities matter most? | you can't maximize all of them; the top 3 decide the structure | "Rank these quality attributes for my product and justify the top 3." |
| How would we measure each one? | "fast" and "scalable" can't be checked; "p95 under 300 ms at 200 requests/s" can | "Rewrite each quality as a scenario with a measurable response." |
| What are the constraints? Team size and skills, deadline, budget, existing systems, regulation, hosting | constraints remove options before preferences do | "Which options do my constraints rule out?" |
| Who builds and runs it? | Conway's law: a system's structure tends to copy the communication structure of the organization that builds it | "Given 1 team of 4, which boundaries can we actually own?" |
| Where are the natural boundaries? | split by business capability, rate of change and data ownership, not by technical layer | "Propose module boundaries by business capability, each owning its data." |
| What is the simplest structure that meets the drivers? | every extra moving part costs operations, debugging and onboarding time | "What is the simplest architecture that meets these drivers? Justify each component." |
| Which decisions are hard to reverse? | spend analysis on one-way doors (data model, service split, language, vendor), decide two-way doors fast | "Classify each decision as easy or hard to reverse." |
| What could go wrong? | risks found on paper are cheap; risks found in production are not | "List the risks, likelihood, impact and the cheapest test for each." |
| How will we know it still holds? | structure erodes one shortcut at a time | "Propose fitness functions that fail CI when a rule is broken." |
| How will we remember why? | the next team needs the reasoning, not just the result | "Write an ADR for this decision." |
The default most experienced architects reach for in a new product with one or two teams is a modular monolith: one deployable, split inside into modules with enforced boundaries. Services get extracted later when a module has a measured reason (independent scaling, team ownership, isolation). Treat a model that jumps straight to microservices for a small team as a sign it is pattern-matching, not reasoning.
Vocabulary
| Term | What it means | Say it like |
|---|---|---|
| Quality attribute (architecture characteristic, "-ility") | a property the system must have beyond its features: performance, availability, security, modifiability, testability, deployability | "Our top quality attributes are modifiability, data integrity and low operating cost." |
| ISO/IEC 25010 | the standard list of product quality characteristics; the 2023 edition names nine: functional suitability, performance efficiency, compatibility, interaction capability, reliability, security, maintainability, flexibility and safety, each with subcharacteristics (maintainability › modifiability, testability) | "Name each quality by its ISO/IEC 25010 characteristic." |
| Quality attribute scenario | a testable statement of a quality: source, stimulus, environment, artifact, response, response measure | "Express availability as a quality attribute scenario with a response measure." |
| Architecture driver | a requirement that shapes the structure: a key use case, a quality attribute or a constraint | "Trace each component back to the driver it serves." |
| Constraint | a decision already made for you: language, cloud, budget, regulation, deadline | "Constraints: TypeScript, one Postgres instance, EU data residency." |
| Module | a unit of code with one responsibility and a public interface; the rest is private | "Each module exposes a public API; nothing imports its internals." |
| Boundary | the line between modules or services that dependencies may only cross through an interface | "Where should the boundaries be, and what crosses each one?" |
| Coupling | how much one part depends on another; lower and narrower is better | "Point out where coupling between billing and orders is too tight." |
| Cohesion | how closely the contents of one module belong together; things that change together should live together | "Group code by business capability for high cohesion." |
| Layered architecture | code split into horizontal layers (UI, business logic, data access), each calling the one below | "Would plain layers be enough here, or does the domain need more isolation?" |
| Dependency rule | source dependencies point inward, toward business logic; the core knows nothing about frameworks or databases | "Check this design against the dependency rule." |
| Dependency inversion | the core defines an interface; infrastructure implements it, so the core doesn't depend on infrastructure | "Invert the dependency on the payment provider." |
| Hexagonal architecture (ports and adapters) | the core defines ports (interfaces); adapters connect them to HTTP, databases, queues, tests | "Structure the order module as ports and adapters with an in-memory adapter for tests." |
| Clean / onion architecture | concentric layers (entities, use cases, adapters, frameworks) with the dependency rule enforced | "Is clean architecture worth the ceremony for a CRUD app this size?" |
| Monolith | one deployable unit containing the whole application | "Keep it a monolith until a module has a measured reason to split." |
| Modular monolith | a monolith split internally into modules with enforced boundaries and owned data | "Design this as a modular monolith with 4–6 modules." |
| Microservices | independently deployable services, each owning its data, talking over the network | "What would microservices buy us, and what would they cost a 4-person team?" |
| Distributed monolith | services that must be deployed or changed together; the costs of both styles, the benefits of neither | "Would this split produce a distributed monolith?" |
| Event-driven architecture | components react to events published through a broker instead of calling each other | "Which interactions should be events instead of direct calls?" |
| Domain event | a record that something happened in the business, named in the past tense (OrderPlaced) | "List the domain events in the checkout flow." |
| CQRS (command query responsibility segregation) | separate models for writes (commands) and reads (queries) | "Is CQRS justified here, or do reads and writes have the same shape?" |
| Event sourcing | storing state as the full sequence of events and rebuilding it by replaying them | "Only suggest event sourcing if we need full audit history; say what it costs." |
| Domain-driven design (DDD) | modeling software on the business domain, in the domain's own language | "Use DDD vocabulary: bounded contexts, aggregates, domain events." |
| Bounded context | a boundary inside which one model and its terms are consistent; "Order" in sales is not "Order" in shipping | "Identify the bounded contexts and draw a context map." |
| Ubiquitous language | the shared vocabulary of domain experts and code | "Build a glossary of our ubiquitous language from these notes." |
| Aggregate | a cluster of objects changed together as one unit, with rules (invariants) it protects | "What are the aggregates, and what invariant does each protect?" |
| Anti-corruption layer | a translation layer that keeps a foreign or legacy model out of your own | "Put an anti-corruption layer in front of the legacy ERP." |
| Context map | a diagram of bounded contexts and how they relate (customer/supplier, shared kernel, anti-corruption layer) | "Draw a context map for these 5 contexts." |
| ADR (architecture decision record) | a short numbered document recording one decision: context, decision, consequences | "Write ADR-0004 for choosing Postgres over MongoDB." |
| C4 model | four zoom levels of diagram: system context, containers, components, code | "Give me C4 level 1 and level 2 diagrams in Mermaid." |
| Fitness function | an automated check that an architectural rule or quality still holds, run in CI | "Write fitness functions that fail the build if domain code imports infrastructure." |
| ATAM (Architecture Tradeoff Analysis Method) | the Software Engineering Institute's method for evaluating an architecture against quality-attribute goals | "Run an ATAM-style evaluation of this design." |
| Sensitivity point / trade-off point | a decision that strongly affects one quality / a decision that affects several qualities in opposite directions | "Mark the sensitivity points and trade-off points." |
| Strangler fig | replacing a legacy system piece by piece behind a facade until the old one can be switched off | "Plan a strangler-fig migration, one capability at a time." |
| Technical debt | the future cost of shortcuts taken now | "Rank the technical debt by cost of delay." |
| Blast radius | how much breaks when one part fails or changes | "What is the blast radius of a bad deploy of the billing module?" |
| Trust boundary | a line where data passes between parts with different privileges; where security checks belong | "Mark the trust boundaries and threat-model them with STRIDE." |
Plain layers and ports and adapters differ in which way the source-code dependencies point:
Trade-off analysis
Ask for trade-offs in a fixed shape so they can be compared and argued with. Two shapes do most of the work.
A quality attribute scenario (the six-part form from the Software Engineering Institute's architecture books) makes a quality testable:
| Part | Example |
|---|---|
| Source | a developer on the team |
| Stimulus | adds a new payment provider |
| Environment | at design time, normal sprint |
| Artifact | the payments module |
| Response | change is confined to one new adapter; no other module changes |
| Response measure | done in under 3 days, zero changes outside payments/ |
An ATAM-style trade-off table compares options against the scenarios and names what each decision touches:
| Decision | Scenario affected | Sensitivity point | Trade-off point | Risk | Non-risk |
|---|---|---|---|---|---|
| async event between orders and invoicing | invoice created within 5 s of order | broker delivery latency | decoupling vs harder debugging and eventual consistency | duplicate events create duplicate invoices | idempotency key on invoice creation |
| one Postgres for all modules | zero lost payments | transaction scope | integrity and simplicity vs modules sharing a failure domain | one module's slow queries starve others | schemas per module keep ownership clear |
A risk is a decision that may cause a quality goal to be missed; a non-risk is a decision judged safe, with the reason. Asking for both stops the model from listing only problems or only praise.
Diagrams and ADRs
Ask for diagrams as text (Mermaid, PlantUML, Structurizr DSL or D2) so you can render, diff and edit them; ask for one C4 level per diagram. What a correct Mermaid C4 container diagram looks like:
C4Container
title Containers: invoicing app
Person(user, "Freelancer")
System_Ext(stripe, "Stripe", "Card payments")
System_Boundary(app, "Invoicing app") {
Container(web, "Web app", "Next.js", "UI")
Container(api, "API", "Bun", "Use cases")
ContainerDb(db, "Database", "PostgreSQL")
}
Rel(user, web, "Uses", "HTTPS")
Rel(web, api, "Calls", "JSON/HTTPS")
Rel(api, db, "Reads and writes", "SQL")
Rel(api, stripe, "Charges cards", "HTTPS")| Check | Why |
|---|---|
| Title and scope on every diagram | readers assume a diagram shows everything |
| One C4 level per diagram | mixing containers and classes makes every box ambiguous |
| Every arrow labeled with intent and protocol | an unlabeled line says only "related" |
| Technology on each container | "API" alone hides the decisions |
| Render it before trusting it | generated Mermaid often has syntax errors, and Mermaid's C4 support lacks some features of C4-PlantUML and Structurizr |
Each C4 level zooms into one box of the level above:
1/4
Level 1, system context: your system as one box, the people who use it and the external systems it depends on. Anyone in the company can read it.
ADR formats: Nygard (title, status, context, decision, consequences: the original 2011 format) and MADR (Markdown Architectural Decision Records: adds decision drivers, considered options, the pros and cons of each and how the decision will be confirmed). One decision per ADR; accepted ADRs are not edited, a new ADR supersedes them. A full example is in Software architecture.
Brief the model
Each input has a slot in the skeleton; the last column says which.
| Input | Why it matters | Example | Slot |
|---|---|---|---|
| Product and domain | boundaries come from the business, not the tech | "B2B invoicing for freelancers: clients, invoices, payments, reminders, tax reports." | <context> |
| Top use cases | the flows the structure must make easy | "1. Create and send an invoice. 2. Client pays by card. 3. Overdue reminders. 4. Quarterly tax export." | <context> |
| Ranked quality attributes, with numbers | decides between otherwise equal options | "1. Correctness of money (zero lost payments). 2. Modifiability (ship weekly). 3. Ops cost under $300/month." | <requirements> |
| Constraints | removes options before preferences do | "TypeScript on Bun, Postgres, one cloud region in the EU, GDPR." | <requirements> |
| Team | Conway's law and operational capacity | "3 developers, no dedicated ops, one on-call rotation." | <context> |
| Scale and growth | prevents both over- and under-building | "≈ 2,000 customers in year 1, ≈ 20,000 in year 3; 50 requests/s peak." | <context> |
| Current state | a redesign starts from what exists | paste the folder tree, dependency graph, pain points, incident notes | <materials> |
| Integrations | external systems shape boundaries and failure modes | "Stripe for payments, Postmark for email, an accounting export to Xero." | <context> |
| Decisions already made | stops the model reopening them | paste existing ADRs; "non-negotiable: Postgres" | <materials>, <requirements> |
| Time horizon | prototype, MVP or 5-year platform need different rigor | "MVP in 3 months; expected to live 5+ years." | <context> |
| Deliverable and reader | the format and depth depend on who reads it | "ADR plus C4 diagrams for the 2 other developers and a non-technical cofounder." | <task> (the deliverable), <context> (the reader) |
What to ask for
| Stage | Deliverable | Ask for it like |
|---|---|---|
| Discover | architecture drivers list | "Extract the drivers: use cases, quality attributes, constraints." |
| quality attribute scenarios | "Write 2 scenarios per top quality attribute, each with a response measure." | |
| utility tree | "Build an ATAM utility tree: qualities → refinements → scenarios, each rated H/M/L for importance and difficulty." | |
| domain glossary | "Draft a ubiquitous-language glossary from these interview notes." | |
| event storming outline | "List the domain events of the business on a timeline, with the commands and actors that trigger them." | |
| Shape | context map | "Identify bounded contexts and the relationship between each pair." |
| module decomposition | "A table of modules: responsibility, data owned, public API, depends on." | |
| candidate architectures | "3 candidate architectures, each in one paragraph and one diagram." | |
| C4 diagrams | "C4 system context and container diagrams as Mermaid." | |
| dependency rules | "An allowed-imports matrix between layers and modules." | |
| Decide | trade-off table | "Score each candidate against the top 3 quality attributes, with reasons." |
| ADR | "An ADR in Nygard format: title, status, context, decision, consequences." | |
| risk register | "Risks: description, likelihood, impact, mitigation, owner, trigger." | |
| spike plan | "The smallest prototype that would retire the riskiest assumption." | |
| Build | folder and package layout | "The folder tree for the modular monolith, one line per folder." |
| interfaces and ports | "The port interfaces for the payments module, in TypeScript." | |
| walking skeleton | "A thin end-to-end slice through every container, to deploy first." | |
| fitness functions | "dependency-cruiser rules and an architecture test for these boundaries." | |
| Evolve | architecture review | "Review this pull request against our ADRs and dependency rules." |
| coupling hotspots | "From this dependency graph, find cycles and the most depended-on modules." | |
| migration plan | "A strangler-fig plan with phases, rollback points and the test that ends each phase." | |
| architecture document | "Fill the arc42 template sections we need for a 2-page overview." |
The prompt chain
The chain's deliverable is an architecture proposal: the drivers, the chosen architecture and what it trades away, ADRs for the hard-to-reverse decisions and C4 diagrams the team can build from. Run the four stages in order; each prompt uses the skeleton and replaces "act as an architect" with the standards an architect would apply (ISO/IEC 25010 qualities, C4, MADR, ATAM).
1. Interview
Use first, before anything is drawn: the drivers decide the architecture, and you may not know which ones matter.
<context>
I'm [your role, e.g. the technical cofounder] at
[organization, e.g. a 3-person B2B SaaS startup]. We are
building [system, e.g. invoicing for freelancers:
clients, invoices, card payments, reminders, tax export].
Where it stands:
[stage: greenfield | prototype | in production].
I'm not an architect. The proposal will be read by
[readers, e.g. 2 developers and a non-technical cofounder].
</context>
<task>
Interview me before designing anything. The end
result will be an architecture proposal (candidate
architectures, a recommendation recorded as ADRs, C4
diagrams); first you need its architecture drivers.
</task>
<requirements>
- At most 10 questions, grouped under: business goals and
key use cases; quality attributes (use the ISO/IEC 25010
characteristics); constraints; team and operations; scale
and growth; existing systems and decisions already made.
- For each question: one line on how the answer changes the
architecture, and 2–3 typical answers I can pick from.
- No architecture, patterns or technologies yet.
</requirements>
<quality_bar>
Before answering, check your questions against:
- Each answer could change a structural
decision; drop any question that couldn't.
- Quality questions ask for a number (a
response measure), not an adjective.
- Nothing I already told you is asked again.
</quality_bar>
<output_format>
Numbered questions under the
group headings, and nothing else.
</output_format>
<process>
Ask all the questions in one message, then stop. When I
answer, restate the drivers as three lists (use cases;
ranked quality attributes as scenarios with response
measures; constraints), mark anything still open [NEEDS
SOURCE], and end with a list of the assumptions you made.
</process>2. Options
Use once the drivers are agreed: left alone, the model picks one familiar pattern; you want to see the real choice.
<materials>
[paste the drivers from stage 1, with my answers]
</materials>
<context>
Team: [team, e.g. 3 developers, no dedicated
ops, one on-call rotation]. Time horizon:
[horizon: prototype | MVP | 5+ year platform].
</context>
<task>
Candidate architectures for this system, so I can
choose one before anything is drawn or written up.
</task>
<requirements>
- 2–4 materially different candidates; one must
be the simplest workable option (a modular
monolith or plain layers). Candidates that
differ only in technology names don't count.
- For each: one paragraph, the modules or services, how it
meets each top quality attribute, the operating load for
this team, and which decisions would be hard to reverse.
- Use ATAM vocabulary: sensitivity points,
trade-off points, risks and non-risks.
- Never invent numbers, names, quotes or sources:
write [NEEDS SOURCE] where support is missing.
</requirements>
<quality_bar>
Before answering, check your draft against:
- Every component serves a numbered driver.
- Each candidate names what it makes
worse, not only what it improves.
- The trade-off table scores every
candidate on every top quality attribute.
- The recommendation names the assumption
that, if wrong, would flip it.
</quality_bar>
<output_format>
One section per candidate; a trade-off table
(candidate | each top quality attribute, scored +, 0
or - with a reason | operating load | hard-to-reverse
decisions); a recommendation in under 100 words.
</output_format>
<process>
End with a list of the assumptions you made. Then stop and
wait for my choice: no ADRs, diagrams or module tables yet.
</process>3. Produce
Use after you have chosen: the full proposal for one candidate, in the form the team will review.
<materials>
[paste the agreed drivers from stage 1]
[paste the chosen candidate and
the trade-off table from stage 2]
[paste existing ADRs, the folder tree
or the integration list, if any]
</materials>
<context>
[product and team, e.g. B2B invoicing for freelancers,
built by 3 developers with no ops]. The readers: [readers,
e.g. the other 2 developers and a non-technical cofounder].
We chose [candidate, e.g. candidate 1, the
modular monolith] because [reason, e.g. the
lowest operating load for a team with no ops].
</context>
<task>
The architecture proposal for the chosen candidate:
the document the team approves and then builds from.
</task>
<requirements>
- Name qualities with their ISO/IEC 25010
characteristics; write the top 3 as quality
attribute scenarios with response measures.
- C4 model: a system context and a
container diagram, one level each, in
[notation: Mermaid | PlantUML | Structurizr DSL | D2];
every arrow labeled with intent and
protocol; technology on every container.
- Each hard-to-reverse decision as an ADR in
[ADR format: MADR | Nygard], status Proposed,
with at least 2 negative consequences.
- Modules by business capability; each owns
its data and exposes a public API;
dependencies point inward, with no cycles.
- Risks and non-risks in ATAM
style, each tied to a decision.
- Never invent numbers, names, quotes or sources:
write [NEEDS SOURCE] where support is missing.
</requirements>
<quality_bar>
Before answering, check your draft against:
- Every component and ADR traces to a numbered driver.
- The diagrams, the module table and the
prose name the same parts, with no extras.
- No module reads or writes another module's tables.
- The operating load fits the team in <context>.
- Each fitness function would fail
CI when its rule is broken.
</quality_bar>
<output_format>
Markdown, under [length, e.g. 4 pages], in these
sections: summary (5 lines); drivers; architecture
overview; C4 diagrams; module table (module |
responsibility | data owned | public API | depends on);
ADRs; quality scenarios and how the design meets each;
risks and non-risks; fitness functions; open questions.
</output_format>
<process>
Ask me up to 3 questions first if anything
missing would change your answer; otherwise go
on. End with a list of the assumptions you made.
</process>4. Review
Run this in a fresh chat, pasting only the proposal and the drivers. A model reviewing its own draft shares its blind spots, so the critique has to come from a chat that didn't write it; for a system that handles money or personal data, have a person review it too.
<materials>
<proposal>
[paste the architecture proposal]
</proposal>
<drivers>
[paste the agreed drivers]
</drivers>
</materials>
<context>
This is a fresh chat: you did not write this proposal.
It goes to [reviewers, e.g. the two developers who
will build it] for approval [when, e.g. on Friday].
</context>
<task>
An ATAM-style review of the proposal before it is
approved: what would make it miss its quality goals.
</task>
<requirements>
- A short utility tree: quality attributes, then scenarios,
each rated H/M/L for importance and difficulty.
- For the 5 highest-rated scenarios: how the
design responds, with its sensitivity points,
trade-off points, risks and non-risks.
- Score the proposal 1–5 on: traceability,
measurable qualities, trade-offs, alternatives,
boundaries, dependencies, fit to team,
reversibility, risks, diagrams, enforcement.
- Do not rewrite the proposal and do not praise it.
- Never invent numbers, names, quotes or sources:
write [NEEDS SOURCE] where support is missing.
</requirements>
<quality_bar>
Before answering, check your review against:
- Every problem cites the section,
diagram or ADR it comes from.
- Problems are ranked by the business
goal they threaten, worst first.
- You compared the diagrams with the module
table, and the ADRs with the drivers.
- If you found fewer than 5 problems,
you say which checks came back clean.
</quality_bar>
<output_format>
The utility tree; a scenario table (scenario | design
response | sensitivity points | trade-off points |
risks | non-risks); the scorecard; the ranked fixes
(problem | evidence | fix | effort S, M or L).
</output_format>
<process>
End with a list of the assumptions you made.
</process>Take the top fixes back to the chat that wrote the proposal: "Apply fixes 1–3, keep everything else, list what you changed." Then rerun stage 4 in another fresh chat if the changes were structural.
Goals and loops
In an agent that runs commands and checks its own work, such as Claude Code, the Produce stage can run until it
measurably passes: /goal keeps starting turns until a condition holds, and /loop repeats a prompt or skill on
an interval. The checker reads only the conversation, so every condition below names a check whose output Claude
prints, the constraints that must survive, and a bound. How to write your own:
Goals and loops.
| Task | Completion condition |
|---|---|
| Write the ADRs for the proposal | /goal every ADR in docs/adr/ has Status, Context, Decision and Consequences, npx markdownlint-cli2 "docs/adr/*.md" reports 0 errors (show its last line), and each ADR names the quality-attribute scenario it serves; or stop after 15 turns |
| Enforce the module boundaries | /goal the architecture test (npx depcruise src --config .dependency-cruiser.cjs) reports 0 violations, shown by its summary line; no rule removed or weakened; or stop after 20 turns |
| Draw the C4 diagrams | /goal npx -p @mermaid-js/mermaid-cli mmdc -i docs/c4.md -o docs/c4.svg renders without errors, and every container in the module table appears in the diagram (list any missing: none); or stop after 10 turns |
Loops that fit: during a migration, /loop 30m to rerun the fitness functions on the branch and report new violations only. For a daily check on main use /schedule: loops stop when Claude Code closes and expire after seven days.
What a checker can't judge: whether the trade-offs suit your business, team and timeline. That stays with the Review stage in a fresh chat and an experienced architect.
Prompt library
One entry per deliverable from What to ask for, outside the chain. Quick is the minimum that still works; Full is the skeleton filled in. Replace each placeholder: pick one option, or write your own value.
Quality attribute scenarios
Stage: produce · Use when: the brief says "fast", "scalable" or "secure" and you need something testable.
Quick
Turn these requirements into quality attribute scenarios
(source, stimulus, environment, artifact, response, response
measure), named by ISO/IEC 25010 characteristic: [paste
requirements]. Check that every response measure is a number
a test could check, and mark each number as mine to confirm.Full
<materials>
[paste the requirements, user stories or meeting notes]
</materials>
<context>
[system, e.g. B2B invoicing for freelancers], built by
[team, e.g. 3 developers]. Expected load: [scale, e.g.
2,000 customers in year 1, 50 requests/s at peak].
</context>
<task>
Quality attribute scenarios for the
qualities these requirements imply, so we
can rank them and design against the top 3.
</task>
<requirements>
- The six-part form: source, stimulus, environment,
artifact, response, response measure.
- Name each quality by its ISO/IEC 25010 characteristic and
subcharacteristic, e.g. maintainability › modifiability.
- 2 scenarios for each of the top 5 qualities: one
in normal operation, one under stress or failure.
- Mark every number you propose
"(proposed)", for me to confirm.
- Never invent numbers, names, quotes or sources:
write [NEEDS SOURCE] where support is missing.
</requirements>
<quality_bar>
Before answering, check your draft against:
- Every response measure is a number with a
unit that a test or a dashboard could check.
- No scenario restates a feature; each describes a quality.
- The ranking follows my requirements, not a generic order.
</quality_bar>
<output_format>
A table: quality (ISO/IEC 25010) | source | stimulus |
environment | artifact | response | response measure.
Then the top 3, ranked, one line each on why.
</output_format>
<process>
Ask me up to 3 questions first if anything
missing would change your answer; otherwise go
on. End with a list of the assumptions you made.
</process>Architecture decision record
Stage: produce · Use when: a decision has been made and needs writing down before people forget why.
Quick
Write ADR-[number, e.g. 0004] in [ADR format: MADR | Nygard]
for: [decision, e.g. one Postgres with a schema per module].
Include 2+ negative consequences and a "revisit if" line.
Check each rejected option has a real reason; mark missing
facts [NEEDS SOURCE].Full
<materials>
[paste the discussion notes, the
trade-off table and any related ADRs]
</materials>
<context>
Our ADRs live in [location, e.g. docs/adr/ in
the repo] and are read by [readers, e.g. the
current developers and whoever joins next year].
</context>
<task>
ADR-[number, e.g. 0004] recording this decision: [decision,
e.g. one PostgreSQL database with a schema per module].
</task>
<requirements>
- Template: [ADR format: MADR | Nygard]. MADR
sections: decision drivers, considered options,
pros and cons of each, confirmation. Nygard
sections: context, decision, consequences.
- Status: [status: Proposed | Accepted]. If it replaces
an earlier ADR, say which one it supersedes.
- At least 2 positive and 2 negative consequences, and a
"revisit if" line naming a condition we could observe.
- One decision only; under one page.
- Never invent numbers, names, quotes or sources:
write [NEEDS SOURCE] where support is missing.
</requirements>
<quality_bar>
Before answering, check your draft against:
- The context states the forces, not the conclusion.
- Each rejected option has a real reason, not a straw man.
- The negative consequences are the ones
a skeptic on the team would raise.
- Someone joining next year could tell from
it whether the decision still holds.
</quality_bar>
<output_format>
Markdown in the chosen template, titled with
the number and the decision in under 10 words.
</output_format>
<process>
End with a list of the assumptions you made.
</process>C4 diagrams
Stage: produce · Use when: you need context and container views to paste into a README and keep in the repo.
Quick
From this description, draw C4 system context and
container diagrams in Mermaid (C4Context, C4Container):
[paste description]. Label every Rel with intent and
protocol, put technology on every container, and check
nothing appears that the description doesn't mention;
list what you couldn't place.Full
<materials>
[paste the architecture description,
module table or proposal]
</materials>
<context>
The diagrams go in [where, e.g. the repo README
and the onboarding doc], read by [readers, e.g.
new developers and a non-technical cofounder].
</context>
<task>
C4 diagrams of this system, as
text we can render, diff and edit.
</task>
<requirements>
- Levels:
[C4 levels: system context | container | component],
one level per diagram.
- Notation:
[notation: Mermaid | PlantUML | Structurizr DSL | D2].
- A title and scope on every diagram; every
arrow labeled with intent and protocol;
technology on every container and data store.
- Draw only elements the description mentions.
- Never invent numbers, names, quotes or sources:
write [NEEDS SOURCE] where support is missing.
</requirements>
<quality_bar>
Before answering, check your draft against:
- Every element and arrow is in the description,
and everything in the description is placed.
- No diagram mixes C4 levels.
- The syntax uses only features the notation has
(Mermaid's C4 support is narrower than C4-PlantUML's).
</quality_bar>
<output_format>
One fenced code block per diagram; then anything you could
not place; then a 3-line legend for non-technical readers.
</output_format>
<process>
End with a list of the assumptions you made.
</process>Module boundaries for an existing codebase
Stage: produce · Use when: a codebase has grown without a plan, changes ripple, and you need modules.
Quick
Here are our folder tree and module dependency graph:
[paste tree and graph]. Infer the business capabilities,
propose target modules (responsibility, data owned,
public API), list the cycles, and give an incremental
plan. Check every step leaves the app shippable.Full
<materials>
<tree>
[paste the folder tree]
</tree>
<graph>
[paste the dependency graph, e.g.
from dependency-cruiser or madge]
</graph>
</materials>
<context>
Pain points: [pain points, e.g. slow builds,
every change touches 5 folders, brittle tests].
Team: [team, e.g. 4 developers, weekly releases].
</context>
<task>
A target module decomposition for this
codebase and an incremental plan to reach it.
</task>
<requirements>
- Modules by business capability, not technical
layer; each owns its data and exposes a public API.
- List the dependency cycles and
the 10 most depended-on files.
- Steps that each leave the app shippable, using
[method: branch by abstraction | strangler fig].
- One fitness function per step that
fails CI if the step regresses.
- Never invent numbers, names, quotes or sources:
write [NEEDS SOURCE] where support is missing.
</requirements>
<quality_bar>
Before answering, check your draft against:
- Every file in the tree lands in exactly one module.
- Every cross-module call in the
target goes through a public API.
- No step needs a code freeze or a big-bang merge.
</quality_bar>
<output_format>
The capabilities; a module table (module |
responsibility | data owned | public API | depends
on); cycles and hotspots; the step plan (step |
what moves | fitness function | rollback).
</output_format>
<process>
Ask me up to 3 questions first if anything
missing would change your answer; otherwise go
on. End with a list of the assumptions you made.
</process>Risk register
Stage: produce · Use when: a design is about to be approved and nobody has listed what could go wrong.
Quick
For this design: [paste design], write a risk
register (risk | cause | likelihood L/M/H | impact
L/M/H | mitigation | cheapest early test |
trigger), 8–12 rows, worst first. Check every risk
names a component or decision: no generic risks.Full
<materials>
[paste the design document, diagrams and ADRs]
</materials>
<context>
Approval is [when, e.g. next week]. Before then
we can spend [budget, e.g. 3 developer-days] on
spikes to test the worst risks.
</context>
<task>
A risk register for this design, to choose
which risks to test before approval.
</task>
<requirements>
- 8–12 risks, each naming the
component or decision it comes from.
- Cover technical, operational, security (trust boundaries,
STRIDE) and organizational risks (Conway's law, skills).
- For each, the cheapest early test: a
spike or prototype that fits the budget.
- Rate likelihood and impact on [scale: L/M/H | 1–5].
- Never invent numbers, names, quotes or sources:
write [NEEDS SOURCE] where support is missing.
</requirements>
<quality_bar>
Before answering, check your draft against:
- No risk could be pasted into another
project's register unchanged.
- Each trigger is observable: a metric, an event or a date.
- The top 3 risks threaten the
top-ranked quality attributes.
</quality_bar>
<output_format>
A table: ID | risk | cause | likelihood |
impact | mitigation | cheapest early test
| owner role | trigger. Worst first.
</output_format>
<process>
End with a list of the assumptions you made.
</process>Fitness functions
Stage: produce · Use when: the rules exist in a document and you want CI to enforce them.
Quick
Our architecture rules: [paste rules]. Stack: [stack,
e.g. TypeScript, Bun, Vitest]. For each rule write an
automated check, what it catches and misses, and how to
run it in CI. Check every option exists in the tool's
current docs; mark any you're unsure of [CHECK DOCS].Full
<materials>
[paste the dependency rules or
allowed-imports matrix, and the folder tree]
</materials>
<context>
Stack: [stack, e.g. TypeScript on Bun, Vitest, GitHub
Actions]. Today the rules live only in a document and
get broken about [frequency, e.g. once a sprint].
</context>
<task>
Fitness functions that fail CI when
an architecture rule is broken.
</task>
<requirements>
- One check per rule, using
[tool: dependency-cruiser | ESLint | architecture test].
- Cover import direction, cycles, imports
of another module's internals, and
domain code importing infrastructure.
- For each: what it catches, what it misses,
and roughly how long it adds to CI.
- Only options that exist in the tool's current
docs; mark any you are unsure of [CHECK DOCS].
- Never invent numbers, names, quotes or sources:
write [NEEDS SOURCE] where support is missing.
</requirements>
<quality_bar>
Before answering, check your draft against:
- Each check fails on a deliberately broken
import; give that import as its test case.
- No check relies on file names when
it could check the import graph.
- The config is complete enough to paste and run.
</quality_bar>
<output_format>
One code block per check, each followed by: rule |
catches | misses | CI cost. Then the CI job snippet.
</output_format>
<process>
End with a list of the assumptions you made.
</process>Migration plan
Stage: produce · Use when: a legacy system or module needs replacing without a big-bang rewrite.
Quick
Current system: [paste summary, tree, pain points].
Target: [paste target design]. Write a strangler-fig
plan: phases, what moves, the facade that switches
traffic, data migration by expand/contract, rollback per
phase. Check every phase leaves the system shippable.Full
<materials>
<current>
[paste the current system's summary, folder
tree, pain points and incident notes]
</current>
<target>
[paste the target architecture or proposal]
</target>
</materials>
<context>
Team: [team, e.g. 3 developers who also handle
support]. Fixed dates: [constraints, e.g. no
deploys in the last week of each quarter].
</context>
<task>
A migration plan from the current system
to the target, one capability at a time.
</task>
<requirements>
- Pattern: [pattern: strangler fig | parallel run],
with the facade or routing that switches traffic.
- Data moves by expand and contract: no step needs downtime,
and no one-way schema change runs without a backup.
- Each phase: what moves, how traffic switches, the
rollback, and the test that proves it is done.
- Phase 1 is the lowest-risk capability
that still teaches us something.
- Never invent numbers, names, quotes or sources:
write [NEEDS SOURCE] where support is missing.
</requirements>
<quality_bar>
Before answering, check your draft against:
- Every phase leaves the system
shippable and can be rolled back.
- No phase moves code and data in
one step without a fallback.
- The plan ends with the old system switched
off, not running forever beside the new one.
</quality_bar>
<output_format>
A phase table (phase | capability | what
moves | traffic switch | data step | rollback
| done when), then the risks of each phase.
</output_format>
<process>
Ask me up to 3 questions first if anything
missing would change your answer; otherwise go
on. End with a list of the assumptions you made.
</process>Code review against the architecture
Stage: review · Use when: a pull request may be eroding the boundaries.
Quick
Rules: [paste dependency rules]. ADRs: [paste relevant
ADRs]. Diff: [paste diff]. List each violation (file,
line, rule or ADR broken, why it matters, smallest fix),
worst first, no style comments. Check you cite a rule
for every finding; if none, say which rules you checked.Full
<materials>
<rules>
[paste the dependency rules or allowed-imports matrix]
</rules>
<adrs>
[paste the relevant ADRs]
</adrs>
<tree>
[paste the folder tree]
</tree>
<diff>
[paste the diff or the changed files]
</diff>
</materials>
<context>
The change: [change, e.g. late-payment fees on
invoices], by [author, e.g. a developer new to the
codebase]. It is due to merge [when, e.g. today].
</context>
<task>
An architecture review of this
change: violations and risks only.
</task>
<requirements>
- Check import direction, module boundaries,
data ownership and the decision in each ADR.
- Severity per finding: blocker (must
fix before merge), major or minor.
- No style or naming comments; do not rewrite the code.
- Never invent numbers, names, quotes or sources:
write [NEEDS SOURCE] where support is missing.
</requirements>
<quality_bar>
Before answering, check your review against:
- Every finding cites a file and line
and the rule or ADR it breaks.
- Each fix is the smallest change that restores the rule.
- If you found nothing, you list the rules you checked.
</quality_bar>
<output_format>
A table: severity | file:line | rule or ADR |
why it matters | smallest fix. Then any rule
the code suggests we should change instead.
</output_format>
<process>
End with a list of the assumptions you made.
</process>Worked example
Weak prompt
Design a microservices architecture
for my SaaS app. Use best practices.What's wrong
- It presupposes the answer (microservices) before a single driver is known.
- No product, team, scale, constraints or ranked qualities, so there is nothing to trade against.
- "Best practices" invites the most generic answer available: an API gateway, a service per noun, Kubernetes, Kafka and a service mesh. That is an architecture for hundreds of engineers, handed to a team of three.
- No deliverable: you get prose, not an ADR, diagrams and a module table you could review.
Strong prompt
<context>
Product: B2B invoicing for freelancers:
clients, invoices, card payments via Stripe,
overdue reminders, quarterly tax export.
Team: 3 developers, one on-call rotation, no dedicated ops.
Scale: about 2,000 customers in year 1 and
20,000 in year 3; 50 requests/s at peak.
Readers: the other 2 developers
and a non-technical cofounder.
</context>
<task>
An architecture proposal I can take to the team: two
candidate architectures, a recommendation recorded
as an ADR, and the views we need to start building.
</task>
<requirements>
- Ranked quality attributes (ISO/IEC 25010 names): 1.
functional correctness of payments: no lost or double
charges; 2. maintainability: one developer ships a
feature a week; 3. operating cost under $300/month.
- Constraints: TypeScript on Bun,
PostgreSQL, EU hosting, GDPR.
- Candidates: a modular monolith, and the
smallest service split you could defend.
- C4 context and container diagrams in
Mermaid; the ADR in Nygard format.
- Justify every component against a numbered attribute.
- Never invent numbers, names, quotes or sources:
write [NEEDS SOURCE] where support is missing.
</requirements>
<quality_bar>
Before answering, check your draft against:
- Every component traces to attribute 1, 2 or 3.
- The trade-offs say what each candidate makes worse.
- Each module owns its data: no module
reads another module's tables.
- The operating load fits 3 developers with no ops.
</quality_bar>
<output_format>
1. Trade-off table: candidate |
attribute 1 | 2 | 3 | operating load.
2. The recommendation as ADR-0001.
3. The two C4 diagrams.
4. Module table: module | responsibility
| data owned | public API.
5. The top 5 risks with mitigations,
and 3 fitness functions.
</output_format>
<process>
Ask me up to 3 questions first if anything
missing would change your answer; otherwise go
on. End with a list of the assumptions you made.
</process>What came back
An illustrative, abridged response:
No questions: the brief covers the decision. Assumptions
are at the end.
1. Trade-offs
Candidate | 1 Correct | 2 Maint. | 3 Cost | Ops load
Modular monolith | + one tx | + | + | low
3 services | - sagas | 0 | - | high
2. ADR-0001: Build a modular monolith
Status: Proposed
Context: 3 developers, no ops; payment correctness is the
top attribute. One PostgreSQL database keeps a payment and
its invoice update in one transaction.
Decision: one deployable, 4 modules, a schema per module.
Consequences: + one deploy, atomic money updates, under
$300/month. - One failure domain: a slow query in one
module can starve the others. - Boundaries hold only if CI
enforces them.
3. C4 context and container diagrams (Mermaid, omitted)
4. Modules
Module | Responsibility | Data owned | Public API
invoicing | create, send | invoices | createInvoice
payments | charge, refund | payments | charge, refund
reminders | overdue nudges | schedules | scheduleFor
tax-export | quarterly CSV | exports | runExport
Reminders runs a nightly job that selects overdue rows by
invoices.due_date and queues the emails.
5. Risks (2 of 5)
- Stripe can deliver a webhook twice: store an idempotency
key per payment event.
- One module's slow query starves the rest: a statement
timeout on each module's database role.
Fitness functions: no import of another module's internal
folders; no cycles between modules; domain code imports no
infrastructure package.
Assumptions:
1. Tax export runs as a quarterly batch job.
2. Reminders go out by email only.
3. Stripe reports payment results by webhook.How an expert judged it
Checked against the prompt's own quality bar:
- Every component traces to an attribute: passes. The single database is justified by attribute 1 (a payment and its invoice in one transaction), the single deployable by attribute 3 and the team size.
- Says what each candidate makes worse: passes, though in the ADR rather than the table: one failure domain, and boundaries that hold only if CI enforces them.
- Fits the team: passes. One deployable, no broker, no cluster to run.
- Each module owns its data: fails. Reminders selects from
invoices.due_datein the invoicing schema: the shared-table coupling the bar ruled out, in a response that says it checked. A change to the invoices table can now break reminders silently, and none of the three fitness functions would notice, because they check imports and this dependency is a SQL query. - Assumptions: worth reading. "Reminders go out by email only" is a product decision for the cofounder, not the model's to make.
Verdict: one structural fix before the team sees it; the rest is ready for the stage 4 review.
The follow-up
In the module table, reminders reads invoices.due_date
directly, which breaks "each module owns its data". Fix
it one of two ways: invoicing adds a query to its public
API (for example listOverdue(asOf)), or it publishes an
InvoiceDue event that reminders stores in its own
schema. Pick one, say why in two lines, and update the
module table, the container diagram and ADR-0001's
consequences. Then add a check that catches this kind of
dependency, such as a database role per module that can
reach only its own schema. List what you changed.Judge the output
| Criterion | Weak | Strong |
|---|---|---|
| Traceability | boxes with no stated purpose | every component and decision names the driver it serves |
| Measurable qualities | "scalable, secure, maintainable" | scenarios with numbers: latency, recovery time, time to change |
| Trade-offs | one option, all upside | each decision names what got worse and why that is acceptable |
| Alternatives | straw men | genuinely different options, rejected for stated reasons |
| Boundaries | by technical layer, shared tables | by business capability; each module owns its data and exposes an API |
| Dependencies | arrows in every direction, cycles | inward toward the domain; acyclic; rules listed |
| Fit to team | 12 services for 3 people | operational load matches team size and skills |
| Reversibility | all decisions treated alike | hard-to-reverse decisions flagged and given more evidence |
| Risks | none, or a generic list | specific risks with likelihood, impact, mitigation and a cheap test |
| Diagrams | mixed levels, unlabeled arrows, won't render | one C4 level each, titled, labeled, renders |
| Enforcement | rules in prose only | fitness functions that run in CI |
The same checks are in every <quality_bar> on this sheet, so the model is asked to run them before it answers; the
rubric is how you confirm it did.
Follow-up prompts:
Which component in your design serves no numbered driver?
Remove it or justify it.Argue for the simplest alternative (a modular monolith /
plain layers) as strongly as you can. Where does your
recommended design lose to it?Pre-mortem: it is 18 months later and this architecture
failed. Write the 5 most likely reasons, then say which
decision today would have prevented each.Which of these decisions are hard to reverse? For each,
what evidence should we gather before committing, and how
cheaply can we get it?Pitfalls
| Pitfall | What it looks like | Counter it |
|---|---|---|
| Hype by default | microservices, Kafka, Kubernetes, service mesh, GraphQL for a small team | give team size and ops budget; "simplest architecture that meets the drivers; justify each component" |
| Generic qualities | "highly scalable and maintainable" with no numbers | demand quality attribute scenarios with response measures |
| Pattern soup | hexagonal + CQRS + event sourcing + DDD everywhere | "where does each pattern pay for itself, and where is it ceremony?" |
| Layer-first splitting | controllers/, services/, repositories/ as the top-level design | ask for modules by business capability |
| Shared database between services | several services read and write the same tables | "each module owns its data; list every cross-module data access" |
| Rewrite instead of migrate | "rebuild it from scratch in the new style" | ask for incremental steps that each leave the app shippable (strangler fig, branch by abstraction) |
| Ignoring the organization | boundaries that cut across team ownership | give the team structure; ask how Conway's law applies |
| Diagrams that disagree with the text | a database in the diagram that the prose never mentions; arrows with no labels | ask it to cross-check the diagram against the module table; render the Mermaid |
| Invented APIs and tool options | plausible but nonexistent library functions or config keys | check every library and tool option against current docs; run the rule |
| Stale conventions | framework versions, folder conventions or APIs from before the model's cutoff | state your versions; paste the current docs for anything version-sensitive |
| Agreeable reviews | "the design looks solid" | "report only problems, ranked; find at least 5 or explain why there are fewer" |
| Security as an afterthought | no mention of authentication, authorization or trust boundaries | ask for trust boundaries and a STRIDE threat model per boundary |
References
- Fundamentals of Software Architecture (Richards & Ford) (opens in a new tab): characteristics, styles, the laws of architecture and trade-off thinking
- SEI: Architecture Tradeoff Analysis Method collection (opens in a new tab): ATAM, utility trees, sensitivity and trade-off points, risks and non-risks
- ISO/IEC 25010:2023 product quality model (opens in a new tab): the standard list of software quality characteristics
- C4 model (opens in a new tab): the four diagram levels, notation and tooling
- Mermaid: C4 diagrams (opens in a new tab): syntax for C4Context, C4Container and related diagrams
- Structurizr (opens in a new tab): C4 models as code, many views from one model
- Michael Nygard: Documenting Architecture Decisions (opens in a new tab): the original ADR format
- ADR GitHub organization (opens in a new tab) and MADR (opens in a new tab): templates and tools for decision records
- arc42 (opens in a new tab): a template for architecture documentation
- Alistair Cockburn: Hexagonal architecture (opens in a new tab): the original ports and adapters article
- Domain-Driven Design Reference (Eric Evans) (opens in a new tab): definitions of bounded contexts, aggregates and the rest
- Martin Fowler: software architecture guide (opens in a new tab), Microservices (opens in a new tab) and MonolithFirst (opens in a new tab): short canonical essays
- microservices.io patterns (opens in a new tab): decomposition, data ownership, sagas, outbox
- Building Evolutionary Architectures (opens in a new tab): fitness functions
- Team Topologies (opens in a new tab): team structures and Conway's law in practice
- Azure Architecture Center (opens in a new tab): reference architectures and design patterns with trade-offs