// writing-specs-people-read.md
Writing Specs People Actually Read
I've written a lot of specs that nobody read. The tell is always the same — a question comes up in week three that the document answered in week one, on page six, in a section called "Considerations."
The problem usually isn't that engineers won't read. It's that the document was written defensively: to demonstrate thoroughness, to pre-empt criticism, to be citable later. Those are all reasonable instincts and they all produce documents that are structurally unreadable.
Lead with the decision, not the context
Most specs open with background. Market conditions, user research, competitive landscape. All of it real, none of it what the reader came for.
Put the decision first:
We're building inline commenting on shared reports, scoped to text selections only. Shipping behind a flag to internal users in August.
Everything below explains why and what it takes.
Now a reader who only has ninety seconds leaves knowing the right thing. A reader who has an hour keeps going. You've served both.
Write the non-goals section first
This is the highest-value section in any spec and it's the one most often skipped. Non-goals are where you convert vague unease into explicit agreement.
## Non-goals
- Threaded replies (v2 — needs a notification model we don't have)
- Commenting on charts or images (unclear selection semantics)
- Real-time presence indicators (separate project, different team)
- Mobile parity at launch (desktop-first, mobile follows in Q4)
Write these before the requirements. It's much easier to describe what you're building once you've drawn the fence around it, and the act of writing non-goals routinely surfaces a scope disagreement you'd otherwise find in week five.
Make requirements testable
A requirement that can't be checked isn't a requirement, it's a mood.
| Instead of | Write |
|---|---|
| "Comments should load quickly" | "Comment thread renders within 200ms at p95 for threads under 50 comments" |
| "Handle errors gracefully" | "On save failure, keep draft text in the composer and show a retry action" |
| "Support long comments" | "Accept up to 5,000 characters; show a counter past 4,500" |
The second column costs more to write and saves vastly more to build against. When an engineer asks "is this done?", the answer should be checkable without finding you.
Show the states, not just the happy path
Every feature has more states than the design covers. List them, even the boring ones, because each is a decision someone will otherwise make alone at 4pm on a Friday.
- Empty — no comments yet
- Loading — thread is fetching
- Populated — the case everyone designed
- Error — fetch failed
- Permission-denied — viewer can read the report but not its comments
- Deleted-in-place — comment removed while another user has it open
That last one is where the actual complexity lives, and it never appears in a mockup.
Keep it under two pages
Not as a stylistic preference — as a forcing function. A two-page limit makes you cut the defensive padding, and what remains is the part that changes what gets built.
Everything that doesn't fit goes into linked appendices. Research findings, competitive teardowns, the eleven-message thread where you settled on the data model — link it all. Nobody needs it inline, and the people who do need it will follow the link.
The real test
Hand the spec to an engineer who wasn't in any of the meetings. Ask them to describe what they'd build. If they get it right, the spec works. If they ask three clarifying questions, fix those three things — that's the fastest edit loop you'll ever get on a document.
Most specs never get that test, which is why most specs stay unread.