Writing Documentation That People Actually Use

I remember writing a runbook for a restaurant chain’s payment processing system back when I was deploying Nagios across their infrastructure. I put in every detail I could think of. Commands, screenshots, configuration files, the works. Then the next month, someone had a database migration problem at 1 AM, searched the wiki, and couldn’t find anything useful. The runbook was three folders deep with a title like “Server Notes v3.” Good documentation doesn’t help if nobody can find it. That’s the lesson I keep circling back to.
Findability Comes Before Everything
You can write the clearest explanation in the world and it means nothing if the person who needs it can’t find it. I’ve lost hours clicking through nested Confluence pages looking for a simple runbook because it was titled something meaningless. Folder structure is the first thing to get right, because once you set it, everyone builds habits around it.
docs/
├── getting-started/
│ ├── installation.md
│ └── quickstart.md
├── guides/
│ ├── authentication/
│ └── deployment/
├── api-reference/
└── troubleshooting/
└── common-errors.md
That structure is self-explanatory. A developer who needs authentication help knows where to go. A new team member can start with getting-started/ without drowning in implementation details. But more important than folders is the title itself. “Authentication Overview” tells nobody anything. “How to Set Up OAuth2 for Our API” does. Write titles that answer the question before the click.
Every document should pass the first-page test: the reader understands what’s in it by scanning the top of the page, no scrolling. Clear headings, a summary paragraph, quick links to the most common tasks. Example from a README:
# Payment Processing Service
A microservice for handling credit card transactions using Stripe.
## Quick Links
- [Installation](#installation) - Get up and running in 5 minutes
- [API Reference](./docs/api-reference.md) - Complete endpoint documentation
- [Troubleshooting](./docs/troubleshooting.md) - Common errors and solutions
I also test my own documents by actually searching for them. Use the terms a confused developer at 3 AM would type. “payment failed error” not “transaction processing exception handling methodology.”
Write for Two Readers
You’re writing for the senior engineer who just needs a quick reference and the junior developer who has never seen your stack before. Both need the same document. The trick is to layer the information so each one gets what they need without wading through the other’s noise.
Start complex sections with a one-sentence summary before you dive in. This lets experienced readers decide whether to keep reading, and gives newcomers a clear picture of what’s coming.
## Database Migration Process
*This section explains how to safely update the database schema in production without downtime.*
First, create a new migration file using the Alembic CLI...
That one italicized sentence is worth its weight. The senior engineer sees “schema update without downtime” and knows this is relevant. The junior sees scope.
The same applies to how detailed you get. Give three levels of explanation: the simple version, the practical version, and the deep dive. Taking API rate limiting as an example:
Our API limits you to 100 requests per minute to keep the service fast for everyone.
Rate limits are enforced per API key. If you exceed 100 requests per minute, you’ll get a 429. The
Retry-Afterheader tells you how long to wait.
Rate limiting uses a sliding window algorithm. Each request timestamp is stored in Redis with a 60-second TTL. When a request arrives, we count timestamps in the last 60 seconds. Above 100 we reject with 429 and calculate
Retry-Afterfrom the oldest timestamp’s age.
Put all three in the document. Different readers need different depth.
Acronyms are another trap. The team might use “K8s” and “RBAC” and “CI/CD” like they’re common knowledge, but documentation lives longer than the current team. I learned this the hard way writing network diagrams for a restaurant chain’s infrastructure — every acronym was expanded, because six months later the network engineer who wrote them moved on and nobody else knew what “ASA” meant. Expand every acronym the first time it appears on every page.
Diagrams help too. Explaining a microservices architecture in text will make eyes glaze over. Use Mermaid for flowcharts and sequence diagrams, or Excalidraw for quick sketches. I use Mermaid all the time for sequence diagrams showing how requests flow between services. A sequence diagram showing an auth handshake between client, server, and auth provider communicates more in one picture than three paragraphs.
Don’t paste chat logs as documentation. I’ve seen it. Someone found the solution in Slack, someone else pasted the whole thread into Confluence with “solution” in the title. Chat logs are full of tangents, context that made sense at the time, and slang. Extract the useful part and write it properly:
## Deployment Error: "Database schema mismatch"
**Symptom**: Deployment fails with "relation 'new_table' does not exist"
**Cause**: Database migrations weren't run before deploying
**Solution**:
```bash
alembic upgrade head
```
Make It Easy to Update
Documentation that’s hard to maintain becomes outdated documentation pretty fast. And outdated docs are worse than no docs at all — at least with no docs, people know to ask questions.
If something can be generated automatically, it should be. API docs from OpenAPI specs. Table of contents from folder structure. Version numbers from your config files. Don’t maintain things manually that a script can keep current.
One thing I always do is include the commands I used to gather information, right in the document. Every runbook I wrote for infrastructure monitoring included the diagnostic commands at the bottom so the next person could update the specs without hunting down how to check them:
## Production Server Specifications
Last updated: 2025-05-23
| Component | Specification |
|-----------|--------------|
| CPU | 8 cores |
| RAM | 32 GB |
| Disk | 500 GB SSD |
To update:
```bash
lscpu | grep "^CPU(s):"
free -h | grep Mem | awk '{print $2}'
df -h / | tail -1 | awk '{print $2}'
```
Screenshots are documentation debt. They can’t be searched, they break accessibility, and they go stale the moment the UI changes. I’ve spent more time than I care to admit updating screenshots in a Confluence page just because a form field moved one pixel. Prefer text and code blocks for everything except actual UI design decisions. If you need to show how something looks, describe it. If you need to show how it works, show the code.
Link to existing documentation instead of rewriting it. This prevents the maintenance nightmare of duplicated content and helps readers discover related information. In Hugo I use relref so the link keeps working even if I reorganize the folder structure.
Keep It Alive
Set a calendar reminder to review documentation every quarter. I learned this pattern from monitoring — you set up Nagios to check your servers every minute, but nobody checks whether the checks themselves are still running. Same with docs. Delete outdated pages, fix broken links, update version numbers. Pruning keeps it healthy.
The cultural part is harder than the technical part. Documentation only works if people actually write it. What I found works: make documentation part of “done.” A feature isn’t finished until the docs exist. Lead by example — when someone asks a question that should be documented, write the answer, link them to it, and show the value. Lower the barrier to contribution. Don’t ask for polished documentation, ask for a first draft. A rough draft is better than nothing.
What I Learned
Most documentation fails on one of three problems: nobody can find it, nobody understands it, or it’s six months out of date. Good documentation isn’t about being thorough — it’s about being findable, layered for different readers, and easy to keep current. Write titles that answer questions, expand acronyms, include the commands you ran, and treat documentation as part of the work, not an afterthought.
Next
- Nagios: A 10-Year Retrospective on Infrastructure Monitoring — runs the same pattern: prove a concept, deploy it, document it, and keep the docs alive for a decade.
- Self-Hosting Plausible Analytics — a simpler guide but the same principle applies: document your decisions while you make them, not after.
Key Takeaways
- Findability matters more than thoroughness: structure your docs with clear titles and folders so a person searching at 3 AM can find what they need
- Write for two readers: layer your documentation so both senior engineers looking for a quick reference and junior developers needing detailed context can use the same document
- Automate what you can — API docs from OpenAPI specs, version numbers from config — and manually maintain what automation can’t cover
- Replace screenshots with text and code blocks; screenshots can’t be searched, break accessibility, and go stale the moment the UI changes
- Include the commands you used to gather information in the document itself, so the next person can update specs without hunting for how to check them