Writing Technical Documentation Developers Will Actually Read
Most technical documentation gets written once and ignored forever. Not because developers don’t want documentation — anyone who’s spent an afternoon reverse-engineering an undocumented API knows how much it matters — but because most docs are written for the author, not the reader. The author already knows how the thing works. The reader is trying to figure it out. These are different problems, and solving the wrong one produces docs that are technically accurate and practically useless.
Why Most Docs Fail
Documentation fails for predictable reasons:
Written for the author. The author explains what they built, in the order they built it. The reader needs to know how to use it, in the order they’ll use it. These are almost never the same order.
Assumes too much context. “Configure the webhook endpoint” assumes the reader knows what a webhook is, where endpoints are configured, and what they’re configuring it to do. Strip the assumed context and spell out the steps.
Tries to cover everything. Comprehensive documentation that’s never read is less useful than focused documentation on the 20% of functionality that covers 80% of use cases. Write for the common case first; edge cases can live in a separate reference section.
Gets written at the end. Documentation written after implementation is written by someone who can no longer remember what was confusing. The questions that seem obvious after you’ve built something were the most important questions before you started.
Know Your Reader Before You Write
The most useful question to ask before writing documentation: who is the reader, and what are they trying to do right now?
The new team member
They need orientation. What is this? Why does it exist? How do I get it running? What should I read first? They don’t need an exhaustive reference — they need enough to start.
The experienced user
They know how the thing works. They’ve hit a specific problem. They need the answer fast. Dense reference docs with good search are more useful to them than any amount of narrative introduction.
The person debugging at 2am
This is your most important reader. They’re under pressure. They’ve already tried the obvious things. They need to know what each error means, what’s likely causing it, and what to try next. “See the troubleshooting section” is a meaningful recommendation. “Check the logs” is not.
Write for all three, but prioritize the 2am reader. If your docs hold up under pressure, they hold up everywhere.
The README That Works
The README is the most-read piece of documentation for most projects. Its job is to answer four questions quickly:
- What is this? One sentence. Not a paragraph. One sentence.
- How do I start? A quickstart that actually runs. On a fresh machine. With the exact commands, not “configure your environment.”
- How do I do the common tasks? Five to eight examples covering the things most users will do most often.
- Where do I go for more? Link to deeper documentation, issue tracker, and how to ask for help.
The failure mode is trying to answer every possible question in the README. Long READMEs get skimmed. Put the quickstart first. Put everything else somewhere linked, not inline.
The quickstart that actually runs
Test it. On a clean environment. The most common README failure is a quickstart that silently assumes bundle exec, a specific Ruby version, a running database, or environment variables that aren’t mentioned. If a new developer has to troubleshoot the quickstart before they can use the thing, the quickstart has already failed.
Code Examples as Documentation
A good code example teaches faster than any amount of prose. The principles:
Real-world examples beat abstract ones. fetch("/api/users") is more useful than fetch(url). Specific beats general.
Show the happy path clearly first. The reader needs to see the thing working before they can understand the variations. Error handling and edge cases come after the core use case, not before.
Runnable examples are better than pseudo-code. Copy-paste code that works on first try builds trust. Code that requires modification before it runs creates friction and uncertainty.
Example:
# Vague — what is "resource"? what does valid response look like?
def create_resource(params)
resource = Resource.new(params)
resource.save
end
# Specific — reader understands immediately what's expected
def create_article(title:, body:, author:)
Article.create!(
title: title,
body: body,
author: author,
published_at: nil # nil means draft
)
end
Keeping Documentation Alive
Docs rot when they’re not adjacent to the code they describe and not treated as part of the work.
Put doc updates in the PR checklist. “Does this change require documentation updates?” is a question, not an action. Make it an action: the PR description template includes a documentation section that requires a response.
Treat wrong documentation as a bug. A wrong doc is worse than no doc — it actively misleads. When you discover documentation that’s inaccurate, fix it immediately, the same way you’d fix a bug. File a ticket if you can’t fix it right now, and mark the doc section as under review.
The best time to update docs is when you find they’re wrong. You’re already oriented. You understand the problem. The fix will take five minutes. An hour later, you’ll be back in a different context and the five-minute fix becomes a 30-minute investigation.
Pro-Tip: Write the README before you write the code. If you can’t explain in one paragraph what the thing does and who it’s for, the design probably needs clarification first. The discipline of defining the public API surface before implementation catches half the design mistakes before you’ve committed to them. Documentation-first is design feedback, not documentation overhead.
What’s Worth Writing vs. What to Skip
Worth writing
- API reference — every parameter, return value, and error. Generated from code where possible; written by hand where not.
- Architecture Decision Records (ADRs) — why you made major design choices. The “why” decays fast from institutional memory; written ADRs preserve it.
- Runbooks — step-by-step procedures for operational tasks. On-call engineers shouldn’t have to think during an incident. Runbooks let them execute.
- Quickstarts and tutorials — opinionated, end-to-end paths for new users. Highly leveraged: one good tutorial serves thousands of first-time readers.
Skip
- Flowcharts of obvious control flow
- Internal implementation details that have no bearing on how to use the thing
- Documentation for behavior so simple that a meaningful example makes it obvious
- Exhaustive coverage of edge cases that real users never hit
The test: would a competent developer, starting fresh, be stuck without this documentation? If yes, write it. If they’d figure it out in five minutes from context, skip it.
Conclusion
Good technical documentation is a form of empathy — it requires genuinely understanding what your reader doesn’t know and needs to learn. The developers who write great docs aren’t necessarily better writers than everyone else; they’re better at stepping outside their own knowledge and seeing the thing from the perspective of someone who doesn’t have it yet. Start with your most stressed reader, cover the quickstart and common cases clearly, keep examples runnable, and treat documentation updates as part of shipping — not a cleanup task that happens after.
FAQs
Q1: How do I get a team to actually write documentation?
Make it frictionless and expected. A documentation section in the PR template that requires a response — even “no docs changes needed” — is more effective than any amount of advocacy. The teams that write good docs have made it part of the definition of done, not a separate activity.
Q2: What tools are worth using for technical documentation?
For code-adjacent docs: Markdown in the repo, rendered by GitHub or a static site generator. For internal wikis: Notion or Confluence if your company already uses them. For API reference: generated documentation (YARD for Ruby, OpenAPI for REST APIs) supplemented by human-written guides. Tool choice matters less than keeping docs close to code and easy to update.
Q3: How long should documentation be?
As short as it can be and still serve the reader’s most likely need. The README for a small library should be one screen. The reference documentation for a complex API can be extensive, but every section should earn its presence. Length is not quality — the edit that removes unnecessary content improves the document.
Q4: Should I document internal code or just public APIs?
Document decisions and non-obvious behavior, not mechanics. A function named calculate_shipping_cost doesn’t need a comment explaining that it calculates shipping cost. A function that uses a non-obvious formula because of a specific carrier’s pricing rules does. The test: would a future reader need to understand the code’s context to understand the choice? If yes, document it.
Q5: How do I know if my documentation is working?
Watch what questions people ask after reading it. Repeated questions about the same topic mean the documentation doesn’t answer it clearly. Track where new users get stuck — onboarding sessions where you watch someone use the docs for the first time are more informative than any amount of writing and waiting.
Check viewARU - Brand Newsletter!
Newsletter to DEVs by DEVs - boost your Personal Brand & career! 🚀