How to Document System Architecture With AI
The new engineer asks how the system actually works and gets a whiteboard photo from two years ago, or an AI answer that confidently names a queue that isn't there. Here is how to document system architecture with AI: the current state, with every component traced to a fact or marked unconfirmed.
Build an Architecture Doc PromptThe diagram nobody trusts, and the one the AI made up
Someone joins the team and asks the reasonable question — how does this system actually work — and there are two bad answers waiting. One is the architecture diagram from two years ago, drawn once for a review and never touched since, which everyone quietly knows is wrong in ways nobody has written down. The other is newer and worse: an AI handed a pile of code and asked to "document the architecture," which produces a clean, confident diagram that names a caching layer that was removed, a service that was renamed, and a queue that never existed.
Both fail the same way. An architecture document is only useful if a reader can trust that it describes the system as it runs today, and both a stale diagram and a fluent hallucination break exactly that trust. The stale one was true once; the invented one was never true; and a reader has no way to tell which parts of either to believe, which makes the whole document worthless for the thing it exists to do — letting someone reason about the system without having to reverse-engineer it first.
This guide is about producing the third thing: a current-state architecture document where every component, every connection, and every owner is either traced to a fact you supplied or marked plainly as unconfirmed. The discipline is not in the prose — it is in refusing to let a single confident sentence stand in for a fact nobody checked.
What the AI documents, and what it never sees
Start from what goes in, because it decides everything the document can honestly say. The AI works from what you hand it — code notes, existing diagrams, interview transcripts, the system facts you already hold — and it assembles those into a structured document. That is the whole of its input. No code is run; it reaches no repository, no cloud account, no network, no database, and no observability system; it discovers no service and no dependency on its own; it verifies no source code and inspects no live system. It cannot see the architecture — it can only shape the description you give it.
Which is why the output is candidate documentation, not a verified record. Every service, flow, and owner in the draft came from your inputs or was filled in by the model to make the document feel complete, and a fluent draft hides the difference. The engineers and system owners who actually run the thing are the ones who confirm it against reality, and nothing here makes the document complete, correct, secure, or current — those are properties the system has or doesn't, not ones a document can assert about itself.
So the method is built around that gap. Because the model cannot check the system, the document has to carry its own evidence — to say, next to each claim, whether it was confirmed from a source, inferred and still needs confirming, or simply unknown. A document that does that is safe to trust in the parts it vouches for; one that states everything in the same confident voice is the hallucination problem with better formatting.
Step 1: Frame the document before drawing anything
Decide who the document is for and what it covers before a single box is drawn, because an architecture document written for everyone serves no one. Name the audience — an engineer joining the team reads differently than one integrating against the system from outside — and the purpose, and then the scope and what is explicitly out of it. An event platform's document might cover ingestion through delivery and deliberately exclude the customers' internal systems; saying so up front stops the document from sprawling into things it cannot know.
Draw the hardest line first: current state versus target state. A document that quietly mixes the system as it runs with the system as it is planned to become is worse than either alone, because a reader cannot tell which world they are in. Keep them in separate sections — current architecture, planned change, target architecture — and hold the rule that a component which does not exist yet never appears in the current-state diagram, no matter how certain the plan. The most common way an architecture document lies is by drawing next quarter's design as though it shipped.
Name the source and the date while you are here, because an architecture document without them is a rumor. Which notes, which interviews, which walkthrough it was built from; when; and who owns keeping it current. A document that says where it came from and when can be checked and can go stale honestly; one that doesn't is trusted long after it stopped being true.
- Fix the audience, purpose, scope, and out-of-scope before drawing — a document for everyone helps no one.
- Separate current from target state. A component that does not exist yet never appears in the current diagram.
- Record the source, the date, and the update owner. An undated architecture document is a rumor.
- The most common architecture-doc lie is drawing the planned design as if it already runs.
Step 2: Map the system context — components, responsibilities, owners
Now lay out the shape: the external actors and systems at the edges, then the major components inside, each with the one responsibility it holds and who owns it. The goal is the boundaries, not the internals — what the pieces are and where one ends and the next begins — because that is the map a reader needs to reason about the system, and it is a different thing from a file-by-file tour of the repository. A component here is a runtime part that owns a responsibility (an ingestion service, a normalization worker, a config store), not a folder in the codebase.
Ownership is the part that gets skipped and matters most, because most real incidents live at a boundary where nobody was sure who owned what. State, for each component, the team or system responsible for it — and separately, for each data store, who owns the data in it. "The metadata database is owned by the platform team; the customer warehouses are owned by the customer" is one sentence that prevents a class of wrong assumptions about who can change what.
This is exactly where an AI will invent to fill a gap, so hold the line component by component. If your notes describe an ingestion service and a delivery service but say nothing about a cache, the document does not get a cache because caches are common. A service, a database, a boundary, or an owner that was not in your inputs does not get drawn — and if the model adds one, that addition is the first thing to catch, because it is indistinguishable in tone from the real ones.
- Map components by runtime responsibility and boundary, not by repository folders — this is not a code tour.
- Give every component and every data store an explicit owner. Boundaries with unclear ownership are where incidents live.
- A component, store, boundary, or owner that was not in your inputs does not get drawn.
- An invented service reads exactly like a real one — catch the additions the model makes to look complete.
Step 3: Document the interfaces and the data flows
Connections carry as much meaning as components, and the load-bearing distinction is synchronous versus asynchronous. A synchronous call — a request that waits for a response — couples the caller's fate to the callee's; an asynchronous message through a queue decouples them, and the difference shapes how the system fails. Mark every interface as one or the other, because a diagram that draws a queue as if it were a function call describes a system that behaves nothing like the real one.
Then trace the data: where it is stored, who owns each store, and the key flows — the path a real request or event takes from the edge to its resting place, through the handoffs that matter. One traced flow, end to end, teaches more than a wall of component descriptions, because it shows the pieces working together rather than sitting in a list. Keep it to the flows that carry weight; an architecture document is not an exhaustive call graph.
If a diagram helps — and for architecture it usually does — the AI can draft one as text or Mermaid, but hold four rules on it. It is drawn only from supplied facts, with no invented component or connection; it must not contradict the prose beside it; the tool assembles the diagram as text and does not render or verify it, so what it looks like on screen is yours to check; and the diagram is a claim about the system, not the architecture itself. A picture makes an error more convincing, not less, so the same evidence discipline applies to every arrow in it.
- Mark every interface synchronous or asynchronous — the difference is how the system fails, not a detail.
- State where data lives and who owns each store; trace one real end-to-end flow rather than listing every call.
- A diagram is drawn only from supplied facts, must match the prose, and is a claim the reader still verifies.
- The tool assembles the diagram as text; it does not render or check it. What it looks like is yours to confirm.
Step 4: Tag every claim, and say what you do not know
This is the step that separates a trustworthy architecture document from a plausible one: every important claim carries its evidence status. Confirmed from a supplied source; inferred and needing confirmation; unknown; or out of scope. "The queue is durable — confirmed from the design notes" and "delivery workers call each warehouse synchronously — inferred, needs confirmation" are different claims, and flattening them into the same flat assertion is how a reasonable guess becomes a fact nobody checked.
The tags people resist writing are "unknown" and "inferred," because a document full of them feels unfinished. It is not — it is honest, and an honest gap is useful where a confident guess is dangerous. Runtime topology, failover behavior, whether an invariant holds under load, the retry count, the throughput: these are exactly the things not visible in code notes, and exactly the things an AI will supply a plausible number for if you let it. "Unknown — needs confirmation from the platform lead" is the correct content there, not a placeholder to be embarrassed about.
The no-invention list is worth stating to the model directly, because every item on it is something it will happily fabricate to complete the picture: a service or database, data ownership, a deployment topology, a request flow, queue semantics, a consistency model, a scale or traffic number, failover behavior, a security boundary, a cloud service or configuration, a team name. If it was not in the inputs, its status is unknown — and unknown, written down, is a question someone can answer, where an invented answer is a wrong belief someone will build on.
- Tag each claim: confirmed from source / inferred — needs confirmation / unknown / out of scope.
- "Unknown" is honest content, not an unfinished draft. A named gap beats a confident guess.
- Topology, failover, retry counts, and throughput are the fields an AI fabricates — mark them unknown unless supplied.
- If a service, boundary, owner, or number was not in the inputs, its status is unknown — never an invented value.
Step 5: Link out, and keep the document alive
An architecture document earns its focus by knowing what it is not, and pointing there instead of absorbing it. It says what the system is and how it works today; it does not argue why each choice was made — that is a decision record, and the document links to the ADR in a line rather than re-litigating the trade-off. It shows the API's role in the system, not its endpoint catalogue — that is API documentation. It shows where an operator would act, not the steps — that is a runbook. And it can show a trust boundary for understanding, but it does not produce a threat list, a risk score, or mitigations — that is a threat model. Each of those is a different document with a different half-life, and folding them in is how an architecture document becomes a thing too heavy to keep current.
That last phrase is the real constraint, because the one thing that kills an architecture document is going stale, and the deeper it reaches the faster it rots. A document scoped to what it can maintain — the durable shape of the system, with the volatile details linked out — survives contact with a changing system. One that tries to be the single source of everything is out of date the week after it is written and abandoned the month after that.
So close it the way it should live: a version, a date, the sources it was built from, and a named owner responsible for updating it when the system changes. And then the step no document can do for itself — an engineer who runs the system reads it and confirms the current state, turns the inferred claims into confirmed or corrected ones, and answers the unknowns. The AI produces the draft and its honest gaps; the people who operate the system are the ones who close them.
- Link the neighbors instead of absorbing them: the why to an ADR, the endpoints to API docs, the steps to a runbook, the risk to a threat model.
- Depth is what makes a document rot. Scope it to the durable shape and link the volatile detail out.
- Close with a version, a date, the sources, and a named update owner — an unowned document goes stale by default.
- The AI drafts the current state and its gaps; an engineer who runs the system confirms it and closes the unknowns.
Common mistakes
The ways an architecture document ends up confident and wrong, most of them because the model filled a gap the notes left open:
- Inventing a component to complete the picture. A cache, a service, or a boundary the inputs never mentioned reads exactly like the real ones — and someone will design against it.
- Mixing current and target state in one diagram. A planned service drawn as if it shipped means a reader cannot tell which system they are looking at.
- Stating everything in one confident voice. Without confirmed / inferred / unknown tags, a reasonable guess and a checked fact are indistinguishable, so neither can be trusted.
- Supplying a number nobody measured. A throughput, an availability percentage, or a retry count invented to look complete becomes a spec someone builds against later.
- Turning the document into an ADR. Explaining why every choice was made buries the current-state description in decision history and makes the document too heavy to keep current.
- Dropping to a file-by-file code tour. Walking the repository folders is onboarding's job; an architecture document maps runtime components and boundaries, not source layout.
- Trusting the diagram because it renders cleanly. A neat diagram makes an invented connection more convincing — the arrows carry the same evidence burden as the prose.
A worked example: a multi-tenant event-delivery platform
Here is a current-state document for a fictional platform that receives product events from many sources, normalizes them, and delivers them to customer warehouses — the kind of system where the interesting architecture is in the boundaries and the failure modes, not the component list.
Watch where the discipline shows: one connection is tagged inferred rather than asserted, several fields stay unknown rather than getting a plausible number, a planned schema-registry service is kept out of the current diagram entirely, and the reasons behind the design are linked to an ADR rather than argued here. The claims that carry weight each wear a tag — confirmed, inferred, or unknown — and where there was nothing to confirm, the document says so instead of guessing.
A current-state document with a text diagram, sync/async boundaries, data ownership, one invariant and one failure path — the load-bearing claims tagged confirmed, inferred, or unknown, the planned service kept out of the current diagram, and no throughput or availability number inventedDOCUMENT HEADER (so a reader knows what they are trusting):
system : event-delivery platform (multi-tenant)
audience: engineers joining or integrating with the platform
scope : current-state ingestion -> normalization -> delivery
out : the customer warehouses' internal schemas; billing
source : design notes + ingestion-service code notes + a walkthrough
with the platform lead
version : v3, 2026-07-16 owner: Platform team
CURRENT-STATE DIAGRAM (text / Mermaid, derived only from supplied facts):
flowchart LR
PROD[Event producers]
API[Ingestion API]
ING[Ingestion service]
Q[(Durable queue)]
NORM[Normalization workers]
DEL[Delivery workers]
CFG[(Tenant config store)]
META[(Metadata database)]
WH[Customer warehouses]
DLQ[(Dead-letter queue)]
PROD -->|sync, authenticated| API
API --> ING
ING -->|enqueue -- async| Q
Q --> NORM
NORM --> DEL
DEL -->|per-event -- INFERRED| WH
DEL --> CFG
DEL -->|on repeated failure| DLQ
ING --> META
DEL --> META
the diagram is a claim, not proof. It is drawn from the notes above and
an engineer who runs the system checks it against reality.
BOUNDARIES:
sync : producers -> Ingestion API (authenticated; the auth boundary)
async : from the enqueue onward -- the queue decouples ingestion from
delivery (the sync delivery-to-warehouse leaf is tagged inferred
below, not asserted)
DATA OWNERSHIP (who owns what, so nobody assumes):
metadata database -> platform: event metadata + delivery status
tenant config store -> platform: per-tenant destinations and rules
customer warehouses -> the customer (out of scope here)
event payloads -> the tenant; transient in the queue, not stored raw
ONE INVARIANT THAT MUST HOLD:
an event accepted for tenant A is only ever delivered to tenant A's
configured destinations. Tenant isolation is the property the whole
design exists to protect.
ONE FAILURE-PROPAGATION PATH:
a tenant's warehouse goes unavailable -> that tenant's deliveries fail
-> retries back up in the queue. IF the delivery-worker pool is shared
with no per-tenant concurrency limit, that backlog could delay OTHER
tenants' deliveries too. Whether such a limit exists is UNKNOWN from the
supplied notes -- so this is written as a risk to confirm, not a fact.
EVIDENCE TAGS (every claim carries one):
Confirmed : the auth boundary, the durable queue, normalization before
delivery, the dead-letter path on repeated failure, the
metadata database (all in the supplied notes)
Inferred : delivery workers call each warehouse per event, synchronously
-- consistent with the notes, not stated. NEEDS CONFIRMATION.
Unknown : retry count and max attempts; whether tenant isolation holds
under load; availability target; throughput
Out of : warehouse internal schemas; billing; how producers are
scope onboarded
PLANNED, NOT CURRENT (kept OUT of the diagram above):
a schema-registry service to replace the inline per-tenant mappings is
planned but not built. It lives in a separate "Target architecture"
section -- putting it in the current diagram would document a system
that does not exist yet.
LEFT TO OTHER DOCUMENTS ON PURPOSE:
WHY a durable queue instead of synchronous delivery -> an ADR
(this doc links it in one line; it does not re-argue the decision)
the ingestion API's request/response/errors -> API docs
what to do when the dead-letter queue backs up at 3am -> a runbook
abuse cases, trust-boundary risk, mitigations -> a threat model
WHAT THIS DOCUMENT DELIBERATELY DOES NOT INVENT:
no throughput number, no availability percentage, no retry count, no
cloud product name. Where the note did not say, the document says
Unknown -- because a made-up number in an architecture doc is the kind
of thing someone designs against a year later.
Where this fits in NewPrompt
The Markdown Output Builder is the tool because an architecture document is a structured document, and its job is to enforce a structure you define. There is no built-in architecture document type, which is the point: you build the section skeleton this guide describes — system context, components and owners, interfaces, data flows, runtime topology, the evidence tags, the links out — and it assembles a prompt that holds that structure, in your browser, running nothing. What comes back is prompt text you run in your own AI tool against your own system facts; it is the same way the README and ADR guides use it, a document shaped to sections you choose rather than a fixed template.
Before you can document a system, you often have to understand it, and that is a different step with its own asset. The Architecture Explanation Prompt is built for reading an existing system's shape from code — its layers, boundaries, and dependencies — and it carries the same discipline this guide leans on, separating what the code shows from what it infers. It is the understand-first step, not the document itself; its output is comprehension you then write up. The Technical Documentation Prompt is a documentation skeleton you can adapt, and its own rule is the one that matters here: document what the system does, not what it might do someday.
Zoomed out, this is one task inside recovering an existing system's architecture. The AI Architecture Recovery Workflow runs from packaging the codebase context, to explaining the current architecture, to finding the risky seams, to documenting the recovered architecture — and this guide is that last step done as a standalone job. Two neighbors mark the edges to stay off: designing a new system from scratch is forward architecture, a different workflow, and recording why a specific decision was made is an ADR. An architecture document describes what the system is and how it works today — living, and rewritten when the system changes; an ADR describes why one choice was made, frozen at its date. Keeping those two apart is what lets each one stay true.