See it as a diagram
Everything below, as a diagram you can edit. Describe yours and see it in seconds.
No account needed · Editable canvas, not a picture
Five things, in this order
One sentence saying what the system does, phrased for someone who does not already know. Not the tagline, the function: this service accepts uploads, validates them against a schema and writes rows to the warehouse.
The runtime shape. What processes exist, what data stores they talk to, what queues sit between them, and which external systems are involved. This is the diagram, and it is the part people scroll to.
The entry points. Where does a request start, where does a scheduled job start, where does an event consumer start. Name the actual file or package, because the next question is always where do I put a breakpoint.
The map from box to directory. For each component in the diagram, the directory that contains it. This is what turns a picture into something a newcomer can act on, and it is the part almost every README omits.
Where to go next. Links to the deeper documents: the architecture file, the ADR index, the runbooks. The README is the index, not the encyclopedia.
## Architecture Ingest accepts CSV uploads, validates them against the contract in `schemas/`, and writes normalised rows to Snowflake.  | Box in the diagram | Code lives in | | ------------------ | -------------------- | | HTTP API | `cmd/api` | | Validator | `internal/validate` | | Loader worker | `internal/loader` | | Schemas | `schemas/` | Requests enter at `cmd/api/routes.go`. The scheduled reconciliation job starts at `cmd/reconcile/main.go`. Deeper: [ARCHITECTURE.md](./ARCHITECTURE.md) - [ADRs](./docs/adr)
What to leave out, and where it goes instead
Sequence diagrams for a single feature. They are useful and they belong next to that feature, not in the front door document that everyone loads. A README with four sequence diagrams is a README nobody scrolls to the end of.
Decision history. Why Postgres instead of DynamoDB is a real question with a real answer, and the answer has a format already: an architecture decision record. Putting it in the README means the reasoning gets edited later by someone who was not there, which is exactly what ADRs exist to prevent. See ADRs versus diagrams.
The full API reference and the full config table. Both should be generated from the source of truth, both are long, and both make the architecture section unfindable. Link to them.
Anything that is true of every service in the company. Company-wide conventions belong in one place, referenced from many, or you will update forty READMEs the next time the convention changes.
Writing it at an altitude that ages well
Prose ages at a rate set by how specific it is. A sentence naming a class that gets renamed is wrong in a month. A sentence naming a directory that gets renamed is wrong in a year, and the rename shows up in the diff so a reviewer can catch it. Write at the directory and component level and the section stays broadly true through several refactors.
The picture ages faster than the prose, because a picture is specific by nature and because updating it is a separate task in a separate tool. That asymmetry is the whole problem with README diagrams: the words survive, the committed PNG does not, and the PNG is the part people look at.
The fix is to stop committing the picture. Point the markdown image at a live embed URL and the README renders whatever the canvas currently holds. Connect the repository through repository sync and the canvas itself is regenerated daily from a branch or a tag, so the image in the README follows the code rather than following whoever last opened the diagramming tool.
The table is the part that breaks, so check it in CI
Every claim in the section is either checkable or it is prose. The box-to-directory table is the checkable part: a path in the right-hand column that no longer exists is a rename nobody carried through, and it is worth fifteen lines of shell to catch on the pull request that caused it rather than on a new joiner in week three.
The check below reads the paths out of the table and fails on the first one that is gone. It is deliberately dumb: no markdown parser, no dependency, nothing to keep up to date when the table grows a column. Run it in the same job as your link checker.
The entry-point lines deserve the same treatment. A grep for each named file in the section, failing when the file is missing, costs another three lines and catches the other rename that silently invalidates the page. Everything else in the section, the one-sentence summary and the links out, ages slowly enough to leave to human review. See docs checks in CI for the rest of the set.
#!/usr/bin/env bash
# Every path in the "Code lives in" column of the README table must exist.
set -uo pipefail
missing=0
while IFS= read -r path; do
[ -e "$path" ] || { echo "README architecture table: missing $path"; missing=1; }
done < <(sed -n '/^| *Box in the diagram/,/^ *$/p' README.md |
awk -F'|' 'NR > 2 && NF > 2 { gsub(/[^A-Za-z0-9_.\/-]/, "", $3); if ($3 != "") print $3 }')
exit "$missing"Check the section the same way you check the code
FAQ
What should the architecture section of a README contain?
Should the architecture live in the README or in a separate file?
How do I stop the README diagram from going out of date?
Why include a table mapping diagram boxes to directories?
Should decision rationale go in the README?