Documentation › Designing a good runbook
Designing a good runbook
A runbook is only as good as the worst moment someone has to use it. Most are written by the person who least needs them. Write for everyone else: the colleague covering your week off, the client's IT person, or you in a year, at an hour when nobody is thinking clearly.
The test for every runbook: could someone who did not write it follow it, under pressure, and get it right the first time?
1.1 Before you write
Answer four questions first. If you cannot answer each in a sentence, the procedure is not ready to be written down.
- What exactly does it do? Name the system and the outcome. "Archive application logs older than 30 days on FS01" beats "Log cleanup".
- When is it used, and when not? The trigger: a ticket type, an alert, a date. Say just as clearly when it is the wrong runbook, and which one to use instead.
- Who will follow it? Write for the least experienced likely operator. If the operators really differ, write two runbooks.
- How do we know it worked? Decide the success check before writing the steps. If you cannot describe what "done" looks like, neither can the operator.
If you draft with an AI tool, put your answers to these four questions in the request, together with runbook-design-guide.md from the download.
1.2 The parts of a good runbook
In the order the operator needs them, and where each one goes in a plain-text runbook:
| Part | What it holds | Where it goes |
|---|---|---|
| Title and scope | What it does, to which system | The header's title line (Section 2.3) |
| Owner and version | Who to ask, and how current it is | Prepared by: and Version: in the header |
| Compatibility | The systems and versions it was written and tested for | Compatible with: in the header |
| When to use it | The trigger, and when it does not apply | A first unnumbered step, such as Before you start, with no code |
| What you need | Roles, permissions, modules, tools, access, a maintenance window, who to tell | The same Before you start step |
| Settings | Every value that changes from one run to the next: names, paths, addresses, limits | The Settings step (Section 2.8) |
| Checks that change nothing | Confirm the right system and the expected starting state | A first section, marked as safe to repeat |
| The steps | One action each, with what to expect and when to stop | Numbered steps in sections (Section 2.5) |
| Verification | Proof that it worked: a check, not a feeling | A last section that checks and records the result |
| Abort conditions | The exact signs that mean stop, and who to tell | Inside the steps where they apply (Section 1.3) |
| Rollback | How to put things back, and how to check that worked | A separate runbook, named in Before you start |
"What you need" is the single most valuable part to get right. Without it, the operator finds out at step 7 that they lack the role step 8 needs, with the system half changed.
Put rollback in its own runbook. Steps unlock in order, so a rollback section at the end would sit in the way of every successful run. Make rollback a separate plain-text runbook, and name it in Before you start.
1.3 Writing steps
Eight habits of a step that works the first time.
- One action per step. If a step needs the word "then", it is probably two steps. Small steps make it obvious where someone stopped and what has already happened.
- Say what they should see. "You should see one line ending in Completed." Without an expected result, the operator cannot tell a pass from a quiet failure.
- Write the stop point into the step. "Stop here if Free (GB) is under 50, and send the number to the owner." Put abort conditions where the operator is looking, not in a section they read an hour ago.
- Look before you touch. Put read-only checks first, in their own section, and say they change nothing. Mark the first section that changes something, so nobody runs it to "have a look".
- Make it safe to run twice. People repeat a step when the window scrolls away or the connection drops. Where you can, write commands that check before they create or delete. Where you can't, say so in the step.
- Use real, tested commands. No placeholders such as
<your-server>inside commands, and nothing copied untested. Values that change belong in Settings, and every other line is the exact command you ran. - Keep secrets out. Have the step prompt for a credential, or sign in interactively (Section 2.9).
- Explain why, briefly. One line of reason ("so the archive does not fill the system drive") lets the operator notice when the situation does not match the runbook, which is when judgment matters most.
1.4 The same step, written twice
Weak:
3. Make sure there's enough space on the server, then move the old logs to the usual folder.
It does not say which server or how much is enough, gives no command, relies on "the usual folder" that lives in one person's head, packs two actions into one step with no stop point between them, and never says what success looks like.
Good:
# C. Check there is room in the archive
# -------------------------------------
# This only reads. It changes nothing.
#
# You should see one row for drive $archive_drive.
# Look at the Free (GB) column.
#
# Stop here if Free (GB) is under $min_free_gb.
# Do not start Section 2. Send the number to the
# runbook owner.
Get-PSDrive -Name $archive_drive
It says it is safe, takes the drive and the limit from Settings, says exactly what to look at, puts the stop point and who to tell in the step itself, and leaves the move for the next step.
1.5 Common mistakes
- Prerequisites found the hard way. Seven steps in, the operator discovers they lack the role step eight needs.
- Written only for the author. Shorthand, skipped "obvious" steps, and context that exists in one head.
- No way back. No abort conditions, no rollback runbook, no check that a rollback worked.
- Placeholders treated as real. Example names, flags and paths copied from a template or an AI draft and never checked against the real environment.
- Never tested by anyone else. An untested runbook only records what its author believes the procedure is.
- Quietly out of date. The system changed and the runbook did not, with no version to warn the operator.
1.6 Testing and upkeep
A runbook is finished when someone else has followed it.
- Run it once, end to end, on a test system or a copy of production.
- Have someone who did not write it follow it while you watch and say nothing.
- Every place they hesitate, ask, or scroll back is a step to rewrite.
- Test the rollback runbook too. It is the one you will need least often and most urgently.
To keep it current:
- Version every change. A date-based version such as
261008.1tells the operator how old it is at a glance. - Keep
Compatible with:true. Update it when you test on something new. - Name an owner.
Prepared by:is who to ask, and who updates it. - Fix it after every run. Anything that surprised the operator goes back into the text before it is forgotten.
- Review it when the system changes, not only on a calendar: upgrades, new modules, renamed servers.
Checklist
Before you hand a runbook over:
- The title names the system and the outcome, and
Compatible with:says what it was tested on. - It says when to use it, and when not to.
- Every role, permission and tool is listed before the first step.
- Every value that changes is a setting. No secrets anywhere.
- Read-only checks come first, and the first section that changes something is marked.
- Each step does one thing and says what to expect.
- Stop points are written into the steps where they apply.
- Every command is real and was run against this environment.
- There is a verification step and a clear definition of done.
- A tested rollback runbook exists and is named.
- Someone who did not write it has followed it.
- It has a version, an owner, and a published hash.
- The Builder builds it without errors, and the preview looks right (Checking the preview).