You wrote the docs. Nobody reads them. The same questions keep coming. Here’s how to write documentation people actually use.

Why Most Docs Fail

Documentation fails for predictable reasons:

  1. Wrong location — Docs in a wiki nobody checks
  2. Wrong time — Written once, never updated
  3. Wrong audience — Too technical or not technical enough
  4. Wrong format — Walls of text when a diagram would work
  5. Wrong content — Explains what, not why or how

Fix these and docs become useful.

The Four Types of Documentation

Different needs require different docs. Don’t mix them.

1. Tutorials (Learning-Oriented)

Goal: Get someone from zero to working

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# Getting Started with Our API

By the end of this tutorial, you'll have made your first API call.

## Prerequisites
- An API key (get one at dashboard.example.com)
- curl or any HTTP client

## Step 1: Test Your Key

Run this command (replace YOUR_KEY):

    curl -H "Authorization: Bearer YOUR_KEY" \
      https://api.example.com/health

You should see: {"status": "ok"}

## Step 2: Make Your First Request
...

Rules:

  • Assume nothing
  • Every step is explicit
  • Show expected output
  • One path, no options
  • Test it on a fresh machine

2. How-To Guides (Task-Oriented)

Goal: Solve a specific problem

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# How to Rotate Database Credentials

## When to Use This
Use this guide when credentials are compromised or 
during scheduled rotation.

## Steps

1. Generate new credentials in AWS Secrets Manager
2. Update the application config:
   ```bash
   kubectl set env deployment/api DB_PASSWORD=$NEW_PASS
  1. Verify connectivity:
    1
    
    kubectl exec -it deploy/api -- psql -c "SELECT 1"
    
  2. Revoke old credentials in Secrets Manager

Rollback

If the new credentials fail, revert:

1
kubectl rollout undo deployment/api
----#`##R`{}*#*`#e**`RSNID#G`AtPNiR`""""utunoomPGraadejineclamcn3aaIEirmssdamrerbl'.lrTeae|po"maesteut:kRvmon:eia:rdR*de/eesn"lt*weeee*ofutts":"e*idxfwesaeTrea:dtrpeLnreryi:b"_hsolroeruspn*cA"atlaeonss:eg*-lattelinkc/e*1il"hpbnce{r2ci:esaeu:i3ecccpdbRY""e"pk(/}yee,,@2rnIsuqse0orcnpsIux2beefeeDi|a6lcpocr.rm-eotriseUp0mvsmfdsl1,eaiEee-rtcnr.1nyidc5olodpDUoTtineoeUm1n-tisI"0tkOancD,:hritr3etili|0oesp:snt0otti0lheoZuedn"tm)ion

Errors:

CodeMeaning
404User not found
401Invalid API key
----#`##Ta---#I--C---*#*`#r#nuRCCNA#G`WauADBrsUErCTDuooocomhTdsueueHtsmroielnmc4aayhiedbsqoeeaemmbespnu.lretriuiuwarinpeusilar:kWi'tgnidCltlg:seraE*dePosgerErCetg*ttrtx*orntisevoehstri*eeaepwUoaernsefaateanntlBnsblmagentnavgt(itauelaiqxtsegtaeevoniedilputtdeeul(svealEmalsaerSoddstectdvt,ssaor{ii(erruiewarttuie{streuyromnibteiwrnmeecjrnettahqsoocgamdtpetfuenhseutnriiaerlxuisn(tSeiasknsliraaarettUaoCsortgt:liiycelnluRleela:vltdfvdrUsdsiHt"etl,aeemcDtskeeo"d(oycrroioeeiel,lnfetssdnrmpspdebrawvsitegeaa"sw@wyenheoaliriwee@eyarnnsclamhxer)tydutpasaxepirieottmapohenrssopmliargelswrlpanpr-ngoiaeelytpoOtogbs.ei)errnglec.nn)iseietvocgeet.nhemodnagen"me)ttTit}"veehrs}ed.i:n)setWmshca.erinelTahytlioeasusstgupiprmvdooeabnstlteehum?ss"::

Rules:

  • Explain why, not just what
  • Connect to concepts readers know
  • Use analogies
  • No steps — this isn’t a how-to

Location Matters

Docs nobody can find are docs nobody reads.

In the Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
def calculate_retry_delay(attempt: int, base_delay: float = 1.0) -> float:
    """
    Calculate exponential backoff delay for retries.
    
    Uses jittered exponential backoff to prevent thundering herd.
    Max delay capped at 60 seconds.
    
    Args:
        attempt: Current attempt number (0-indexed)
        base_delay: Initial delay in seconds
        
    Returns:
        Delay in seconds before next retry
        
    Example:
        >>> calculate_retry_delay(0)  # First retry
        1.0
        >>> calculate_retry_delay(3)  # Fourth retry
        8.0  # (approximately, with jitter)
    """

Put it where people look first: the code.

In the README

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# Service Name

One sentence: what this does.

## Quick Start

    docker-compose up
    curl localhost:8080/health

## Documentation

- [Getting Started](docs/getting-started.md)
- [API Reference](docs/api.md)
- [Deployment](docs/deploy.md)

## Development

    make test
    make lint

README is the front door. Keep it minimal, link to details.

Near the Workflow

1
2
3
4
5
6
7
8
9
# deploy.yml
# 
# Deployment workflow for production
# 
# BEFORE RUNNING: Ensure you've completed the pre-deploy 
# checklist: docs/deploy-checklist.md
#
# ROLLBACK: If deployment fails, run:
#   kubectl rollout undo deployment/api

Put docs where they’re needed, when they’re needed.

Keep It Current

Stale docs are worse than no docs — they actively mislead.

Docs as Code

repo/stdreocsc/tssgaaeprtict-hirinetgfe-ecsrtteuanrrcete.e.mdmd.dmd

Docs in the repo, reviewed in PRs, versioned with code.

Automated Checks

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# CI pipeline
docs_check:
  script:
    # Check for broken links
    - markdown-link-check docs/*.md
    
    # Verify code examples run
    - python docs/test_examples.py
    
    # Check API docs match implementation
    - ./scripts/verify-api-docs.sh

Make doc freshness a CI check.

Ownership

Every doc has an owner. When it goes stale, they fix it or delete it.

1
2
3
4
5
6
---
title: Database Schema Guide
owner: @alice
last_reviewed: 2026-02-15
review_frequency: quarterly
---

Writing Tips

Lead with the Action

1
2
3
4
5
6
7
# Bad
The user management system allows administrators to 
perform various operations on user accounts...

# Good
To create a user:
    curl -X POST /users -d '{"name": "Alice"}'

People skim. Put the important thing first.

Use Real Examples

1
2
3
4
5
6
7
# Bad
curl -X POST /endpoint -d '{"field": "value"}'

# Good
curl -X POST https://api.example.com/users \
  -H "Authorization: Bearer sk_live_abc123" \
  -d '{"name": "Alice Chen", "email": "alice@company.com"}'

Real examples are copy-pasteable and show actual use.

Show Don’t Tell

1
2
3
4
5
6
7
8
9
# Bad
The retry logic uses exponential backoff.

# Good
The retry logic uses exponential backoff:
- Attempt 1: wait 1 second
- Attempt 2: wait 2 seconds  
- Attempt 3: wait 4 seconds
- Attempt 4: wait 8 seconds (max)

Concrete beats abstract.

1
2
3
Deploy using our [standard process](deploy.md). 
If you hit issues, check the [troubleshooting guide](troubleshoot.md)
or ask in #platform-help.

Don’t repeat — link to the source of truth.

The Documentation Checklist

Before publishing:

  • Tested all code examples
  • Checked all links work
  • Read by someone who didn’t write it
  • Clear owner assigned
  • Review date scheduled

Good documentation is a product. Treat it like one.


The best documentation is documentation you don’t notice — it’s just there when you need it, answers your question, and gets out of the way.