Module 7: Documentation That Survives
The README that onboards
Overview
The previous lesson established what to document —the stable, high-ROI— and this one goes down to the most stable, most read, and worst-made piece in almost every project: the README. The README is a new dev's first contact with a system. It's the first thing they open when they clone the repo, and in the first few minutes it decides whether the system seems accessible or impenetrable. A good README answers four questions the new dev has right now: what it does (to orient themselves), how to run it (to get it going on their machine), where the pieces are (to know where to go), and how to contribute (to make their first change without breaking the process). A README that answers those four turns onboarding into hours; a README that doesn't —or that doesn't exist— turns it into days of discovering everything the hard way.
This lesson's thesis is that the README isn't decoration: it's onboarding infrastructure, and its value is measurable. The cost of a new dev reaching their first useful commit isn't a fuzzy number —it's the concrete sum of the obstacles they face: fighting to run the project, guessing what module does what, configuring environment variables with no instructions, not knowing how to run the tests—. A good README doesn't "document" those obstacles; it eliminates them, giving the exact instruction that dissolves them. This lesson executes the onboarding cost with and without a README, and shows the difference isn't cosmetic: it's the difference between 3.5 days lost per dev and less than a day, multiplied by every person who joins the team. The README is one of the highest-ROI doc pieces there is —stable (changes little), universally read (every new dev, every time)— and that's why neglecting it is one of the most expensive.
Connection with the module. It's the concrete application of lesson 5 (document the stable) to the most stable piece of all, and the most direct connection with the bus factor of lesson 7: the README is what lets a new dev get going without depending on a person. With the module's analogy: the README is the manual the previous owner left you —where the water valve is, how the water heater lights— that lets you operate the house from day one instead of discovering it the hard way. Frontier with the rest: the README points to the other pieces of the system (to the C4 for the detailed map, to the ADRs for the why), but doesn't replace them —it's the front door, not the complete documentation—; and we don't re-teach here how to write those other pieces, only how the README links to them.
An analogy: the house with a manual vs. the house where you discover everything the hard way
Let's go back to the day you move into a house you didn't build —the module's analogy, now in its most concrete form—, and measure the time of the two versions.
The house where you discover everything the hard way. You arrive and there's nothing. The first night, you grope the wall for half an hour looking for the living-room switch. The first winter, the water comes out freezing and you spend a whole afternoon figuring out how the water heater lights —gas? electric? where's the pilot?— until you call someone. The first time a breaker trips, you switch all twenty off and test them one by one. The first downpour that floods the patio, you run around looking for the water shut-off valve buried behind some pots. Every basic operation of the house costs you hours of discovery, because no one distilled what they already knew. And worst of all: that cost is paid by every person who moves in —the next tenant will again spend half an hour looking for the switch—.
The house with a manual. You arrive and in the kitchen there's a folder: "The living-room switch is on the right as you enter. The water heater is gas: knob on the left of the garage, pilot with the lighter next to it. The breakers are labeled; the kitchen one is the third from the top. The water shut-off valve is in the garden, behind the rosebush, green cover." In ten minutes you know how to operate the house. When a breaker trips, you go straight to the right one. When the patio floods, you shut the valve in thirty seconds. You pay no hour of discovery, because the previous owner already paid it once and gave it to you distilled. And that gift is inherited: you leave it for the next person, who also won't suffer.
Here's the README, exactly: it's the folder the previous owner left you, applied to the software system. "How to run the project" is "how the water heater lights". "Where the pieces are" is "where each breaker is". "How to contribute" is "how the trash goes out, what day the truck comes". Without a README, each new dev discovers the system the hard way —fights for hours to run it, guesses which module to touch, configures blindly—, and that cost is paid by every person who joins. With a README, the new dev operates the system from day one, because whoever was there before distilled what they learned and left it written. The difference between the two houses isn't that one is better —it's the same house—; it's that in one the knowledge of how to operate it survived the change of owner. This lesson measures, in hours, how much that folder is worth.
Worked example: the onboarding cost with and without a README
We're going to measure the time to a new Mercado dev's first useful commit —the moment they stop being blocked and start contributing—. That time is the sum of the obstacles they face before being able to contribute. We take six typical obstacles, and for each we measure how much it costs without a README (the dev discovers it the hard way) and with a good README (the exact instruction dissolves it):
# The README that onboards: the new dev's first contact. We measure the
# time to the FIRST USEFUL COMMIT as the sum of the obstacles they face.
# A good README doesn't decorate: it ELIMINATES obstacles (like running the project, where
# the pieces are, how to configure the environment). We compare onboarding with and without.
BLOCKERS = [
# (obstacle, hours_without_readme, hours_with_readme)
("run the project locally", 8.0, 0.5),
("locate the pieces (what does what)", 6.0, 0.5),
("configure env vars and secrets", 4.0, 0.25),
("know how to run the tests", 3.0, 0.25),
("find where to make the change", 5.0, 1.0),
("know the contribution flow", 2.0, 0.1),
]
print(f"{'blocker':<36}{'no README':>12}{'with README':>12}")
print("-" * 60)
without = with_ = 0.0
for name, wo, wi in BLOCKERS:
without += wo
with_ += wi
print(f"{name:<36}{wo:>10.1f}h{wi:>11.2f}h")
print("-" * 60)
print(f"{'TIME TO THE FIRST USEFUL COMMIT':<36}{without:>10.1f}h{with_:>11.2f}h")
print()
print(f"Without README: {without:.0f} h (~{without / 8:.1f} days of work lost per dev)")
print(f"With README: {with_:.1f} h (less than a day)")
print(f"The README saves {without - with_:.1f} h per new dev "
f"({without / with_:.1f}x faster).")
NEW_DEVS_PER_YEAR = 6
print(f"With {NEW_DEVS_PER_YEAR} new devs a year: saves "
f"{(without - with_) * NEW_DEVS_PER_YEAR:.0f} h/year of onboarding.")
What to expect. Running the file, the output is exactly this:
blocker no README with README
------------------------------------------------------------
run the project locally 8.0h 0.50h
locate the pieces (what does what) 6.0h 0.50h
configure env vars and secrets 4.0h 0.25h
know how to run the tests 3.0h 0.25h
find where to make the change 5.0h 1.00h
know the contribution flow 2.0h 0.10h
------------------------------------------------------------
TIME TO THE FIRST USEFUL COMMIT 28.0h 2.60h
Without README: 28 h (~3.5 days of work lost per dev)
With README: 2.6 h (less than a day)
The README saves 25.4 h per new dev (10.8x faster).
With 6 new devs a year: saves 152 h/year of onboarding.
Read the table obstacle by obstacle, because each line is a concrete fight the README turns into an instruction.
The most expensive obstacle: running the project (8h → 0.5h). Without a README, getting the project running on your own machine is an odyssey: what language version, what dependencies, what database, what services to bring up, in what order, what fails and why. A new dev can lose a whole day just on this —fighting setup errors that have nothing to do with the real work—. A good README dissolves it in half an hour with the exact sequence of commands: "install this, run this script, bring up this, done". It's not that the dev is smarter with a README; it's that they're not discovering the setup, they're following it. That single obstacle justifies the README.
The other obstacles, the same story. Locating the pieces —knowing what module does what— costs 6h without a README (reading code blindly) and 0.5h with a README that has a map or links to the C4. Configuring environment variables and secrets: 4h of guessing against 0.25h with a list of what variables are needed and where to get them. Knowing how to run the tests: 3h against 0.25h. Finding where to make the change: 5h against 1h (the README orients, though this obstacle depends more on the code). Knowing the contribution flow —how PRs are opened, who reviews what—: 2h against 0.1h. In each case, the pattern is the same: without a README the dev discovers the hard way, with a README they follow an instruction, and discovering costs an order of magnitude more than following.
The total: 28h against 2.6h, 10.8 times faster. Without a README, the new dev takes 28 hours —three and a half days of work— just to reach the point of being able to contribute; that's purely lost time, spent on obstacles that have nothing to do with the problem they came to solve. With a README, they take 2.6 hours —less than a day—. The difference, 25.4 hours per dev, isn't a luxury: it's real time of expensive people, multiplied by every person who joins. With six new devs a year —normal turnover in a medium team—, the README saves 152 hours a year: almost a person-month of work that, without a README, is burned on hard-way onboarding. And the README that produces that saving is a stable piece (changes little: how to run the project doesn't change every week) that's written once and yields on every onboarding —very high ROI, exactly what lesson 5 predicted—.
As bars, the contrast looks like this:
Time to the first useful commit (hours)
no README |############################ 28.0h (~3.5 days lost)
with README |### 2.6h (less than a day)
────────────────────────────
10.8x faster. With 6 devs/year: 152h saved (~one person-month).
Deep dive: what makes a README that really onboards
The experiment measured the value of a good README, but didn't say what makes it good. It's worth getting concrete, because most READMEs fail for specific and avoidable reasons.
A README that onboards answers, in this order, four questions —and the order matters, because it's the order the new dev has them—. First: what is this? One or two sentences saying what the system does and for whom, so the dev orients themselves before anything ("Mercado is the marketplace that connects buyers and sellers; this repo is the Internal API"). Without this, the dev reads commands without knowing what they're working on. Second: how do I run it? The exact and tested sequence of commands to get the system running on your own machine, including the dependencies, the database, the environment variables. This is the most important section and the most neglected: a README whose "how to run it" doesn't work is worse than no README, because it promises and fails. Third: where is everything? A brief map of the pieces —what folder or module does what— or a link to the C4, so the dev knows where to go when they have to change something. Fourth: how do I contribute? The workflow —how PRs are opened, how the tests are run, what conventions there are— so the first change doesn't collide with the process.
The criterion that separates a good README from a bad one is brutal and simple: can a new dev, following only the README, get the project running and make a trivial change, without asking anyone? If the answer is no —if at some point they have to go ask because the README isn't enough—, the README failed at its only mission. This criterion can be tested: sit a new dev (or yourself on a clean machine) down and observe where they get stuck following the README; each place where they have to ask is a gap to fix. READMEs almost always fail at the "how to run it": they have steps that assume knowledge the author had and forgot to note ("obviously you bring up the database first"), or that worked on the author's machine but not on a clean one, or that fell out of date when the setup changed. That's why the "how to run it" must be tested on a clean machine, not written from memory.
There's a tension with lesson 5 worth resolving, because it seems contradictory. We said you don't document the volatile, and the "how to run the project" could seem volatile (the setup steps change). Shouldn't it be generated instead of written? The answer: the "how to run it" is actually quite stable —the high-level sequence (install dependencies, bring up the database, run the server) changes little, even if the fine details evolve— and, more importantly, the best version of the "how to run it" does tend toward the generated/executable: a setup.sh script or a docker compose up that is the how-to-run-it (executable, can't desync because if it doesn't work, you don't start). The ideal README for the setup isn't a paragraph of steps that rot, but an instruction pointing to something executable ("run make dev") plus the context of what it does. Thus the README inherits the best of living documentation: the volatile part of the setup lives in a script tested in CI, and the README just frames it. The stable rule is respected: the README documents the stable intention and delegates the volatile detail to something executable.
One last point about the link with the bus factor, which lesson 7 will develop. The real value of the README isn't only saving onboarding hours —it's that that saving doesn't depend on a person. Without a README, the new dev reaches their first commit by asking someone on the team (Elena, whoever knows), which means two bad things: it takes time from that person, and it makes the onboarding depend on that person being there and willing to help. With a README, the new dev gets going alone, without consuming anyone and without depending on anyone. The README is, at bottom, the way for the knowledge of "how this system is operated" —which normally lives in the team's heads— to survive and be available with no intermediaries. It's a direct contribution to the bus factor: it turns tribal knowledge (you have to ask someone) into available knowledge (it's written).
Common mistakes
The README that doesn't let you run the project (the worst). What happens: the README has a nice description of the system, maybe a diagram, but its "how to run it" section doesn't work —it has steps that assume knowledge, are out of date, or are simply missing—, so the new dev gets stuck on the setup and ends up asking. Why it happens: the author wrote the "how to run it" from memory, from a machine that already had everything configured, forgetting the steps that were automatic for them; and they never tested it on a clean machine. How to spot it: if a new dev can't run the project following only the README, or if the "how to run it" hasn't been tested from scratch in a long time, it's broken. How to fix it: test the "how to run it" on a clean machine (or have a new dev test it and note every place they get stuck), and prefer an executable script (make dev, docker compose up) over a list of steps that rots. The "how to run it" is the most important section; if it fails, the README failed.
The README that describes but doesn't orient (the brochure). What happens: the README explains what the system does eloquently —paragraphs about the vision, the architecture, the team's values— but doesn't say how to run it, where the pieces are, or how to contribute; it's a marketing brochure, not an onboarding manual. Why it happens: writing about the vision is more pleasant and "presentable" than writing the boring sequence of setup commands. How to spot it: if your README impresses but doesn't let you do anything —run, locate, contribute—, it's a brochure. How to fix it: trim the vision prose to one or two sentences (what it is and for whom) and dedicate the bulk to the actionable: how to run it, where everything is, how to contribute. The new dev doesn't need to be inspired; they need to get going.
The README written once and never updated (the fossil). What happens: the README was good on day one, but the setup changed, pieces were added, the contribution flow changed, and the README stayed the same —so now its instructions fail and send the new dev down dead ends—. Why it happens: the README isn't in the flow of changes (no one updates it when the setup changes), exactly the proximity problem of lesson 2. How to spot it: if the README mentions steps or pieces that no longer exist, or if new devs "know" to ignore certain parts, it's a fossil. How to fix it: apply docs-as-code (lesson 3) —the README lives in the repo, is reviewed in the PRs that change the setup, and if possible its executable part is validated in CI (the make dev that runs in the pipeline guarantees the "how to run it" works)—. A README that's not maintained becomes the rotted wiki of lesson 2, with the aggravator that it's the first thing everyone who arrives sees.
Exercises
Exercise 1 — Prioritize the sections. A team has time to write only one section of their README this week. The candidates are: (a) an eloquent description of the product vision; (b) the exact and tested sequence of how to run the project; (c) a glossary of domain terms; (d) the team's bio. Using the onboarding-cost example, say which they should write first and why, and what this tells you about a README's priorities.
See solution
They should write (b) how to run the project first, no doubt. In the example, "run the project locally" is the most expensive obstacle of all: 8 hours without a README, the single largest source of lost time. It's also the most blocking obstacle: if the new dev can't run the project, they can't do anything —not explore, not test, not change—, so everything else is blocked behind this. Writing the exact and tested sequence of how to run it dissolves the biggest obstacle and unblocks everything else. It's the highest-ROI section by far.
The other three are much less urgent or directly dispensable: (a) the product vision is pleasant but unblocks nothing (the dev can contribute without an essay about the vision); (c) the glossary helps but is secondary to being able to run the system; (d) the team's bio doesn't help onboarding at all. What this says about a README's priorities: prioritize the actionable and blocking over the descriptive and pleasant. A README is judged by whether it lets you do (run, locate, contribute), not by whether it reads nicely. The practical rule: write first what, if missing, leaves the new dev stuck and unable to advance —and that's, almost always, "how to run the project"—.
Exercise 2 — The README that promises and fails. The text says a README whose "how to run it" doesn't work is worse than no README. Explain why —what extra harm a README with broken instructions causes that the total absence of a README wouldn't—.
See solution
A README with broken instructions is worse than none for several concrete reasons. First, it wastes more time: without a README, the new dev knows they're on their own and seeks help soon (asks, explores the code); with a README that seems complete, the dev trusts it, follows its steps, hits an error, assumes they did something wrong, retries, debugs the wrong problem —loses hours trying to make instructions work that can't work because they're broken—, before giving up and asking for help. The false promise sends them down a pit.
Second, it destroys trust in all the doc: when the dev discovers the README's "how to run it" doesn't work, they stop trusting not only that section but the whole README —and probably all the project's documentation—, exactly the trust chasm of lesson 2. A broken README teaches the new dev, on their first day, that "here the doc doesn't work, better ask"; and that lesson poisons their relationship with all future documentation. Third, it's a trap that's inherited: every new dev falls into the same broken promise.
The absence of a README is honest ("there's no guide here, you'll have to figure it out"); a broken README is a lie ("follow these steps" when the steps lead nowhere). That's why the text insists on testing the "how to run it" on a clean machine: a setup README that hasn't been tested is probably a broken promise waiting to harm the next person who arrives. Better a short and true README than a complete and false one.
Exercise 3 — README and bus factor. The text says the README is "a direct contribution to the bus factor". Explain the mechanism: how exactly does a good README raise the system's bus factor, and what happens to the bus factor when onboarding depends on asking a person instead of reading the README?
See solution
The mechanism is this: the knowledge of "how this system is operated" —how to run it, where the pieces are, how to contribute— normally lives in the team's heads, and when a new dev needs it, they ask someone who knows. That means that operational knowledge depends on the people who have it being available: if they all leave (or just the one who usually helps), the knowledge of how to get the system running goes with them, and a new dev would be stranded, unable to run the project. A good README takes that knowledge out of the heads and puts it in writing, available with no intermediaries: now "how the system is operated" doesn't depend on any particular person being there —it's in the repo, anyone reads it—. That's literally raising the bus factor of that operational knowledge: it goes from living in heads (which leave) to being documented (which stays), just as documenting the stable part of payments raised its bus factor from 1 to 2 in lesson 1.
When onboarding depends on asking a person, two things happen that lower the system's resilience. First, that person becomes a bottleneck and a dependency point: each new dev consumes their time, and if that person leaves or is overloaded, onboarding stalls —the system depends on them to bring people in—. Second, the operational knowledge is never made explicit, so it stays in "tribal" mode: everyone knows it by word of mouth, no one wrote it down, and the day the generation that knows it fully turns over, it's lost. An onboarding that depends on asking keeps the bus factor low (the knowledge lives in heads); an onboarding by README raises it (the knowledge lives written). That's why the README isn't only efficiency —it saves the 152 hours a year—; it's insurance: it guarantees that bringing people in and operating the system doesn't depend on a specific person being there to explain it. It's lesson 7 in miniature, applied to the startup knowledge.
Summary and next step
In this lesson you went down to the most stable, most read, and worst-made doc piece: the README that onboards. You saw that it answers four questions the new dev has now —what the system does, how to run it, where the pieces are, how to contribute— and that its value isn't cosmetic but measurable. With the house with a manual vs. the house where you discover everything the hard way, you understood that the README is the folder the previous owner left you: it lets you operate the system from day one instead of discovering it the hard way. And you measured it: the time to the first useful commit drops from 28 hours (3.5 days lost) to 2.6 hours with a good README —10.8 times faster—, and with six new devs a year that's 152 hours saved. You learned what makes a README good (it answers the four questions, and the "how to run it" works, tested on a clean machine), why a broken README is worse than none (it promises and fails, destroys trust), and how the README raises the bus factor by taking the operational knowledge out of the heads and putting it in writing.
Before moving on you should be able to: name the four questions an onboarding README answers; explain why the "how to run it" is the critical section and must be tested on a clean machine; and connect the README with the bus factor (tribal knowledge → available knowledge).
Lesson 7 rises to the heart of the module, the idea that has been beating under all the previous ones: the bus factor and knowledge sharing. You're going to simulate who leaves Mercado and what modules are orphaned, identify the single points of failure, and compare the insurances for raising the bus factor —documenting the stable against training a second human owner—, measuring which is cheaper. Everything in the module converges there: living documentation, docs-as-code, the C4+ADR+arc42 system, documenting the stable, the README —all of it exists, at bottom, so the knowledge doesn't depend on a single head—. The next lesson makes it explicit and measures it.
Resources
- Make a README (makeareadme.com) — a practical guide to what sections a good README has and why; useful as a checklist for this lesson's four questions. In English.
- GitHub — About READMEs — the reference for how the README is the first contact with a repo and what's expected of it. In English.
- Cyrille Martraire, Living Documentation (Addison-Wesley, 2019), on onboarding and "guided tour" — how the startup doc (the equivalent of the expanded README) reduces the cost of bringing people in and why it must live close to the code. In English.
- The Twelve-Factor App — the factor on build/run and explicit dependencies — why a project must be able to be brought up with explicit and reproducible steps (the basis of a good "how to run it" that doesn't fail on another machine). In English.
- Write the Docs — on README and project documentation — the community that systematizes how to write project doc people actually use. In English.