Craft
Writing a Technical PRD Without Designing the System
When the consumer is another service, the what/how line does not move — the user does. One test for which side any line belongs on.
The advice to state what must be true rather than how to build it is easy to follow when the user is a person. It gets slippery the moment the user is another service, because then the observable behaviour is technical — status codes, payload shapes, retry semantics — and it starts to feel like the PRD has to become a design document.
It does not. The line does not move; the user does. Everything a consumer can observe is yours to specify. Everything they cannot is not.
The test
One question, applied to any line you are unsure about:
If this changed, would a consumer notice?
If yes, it belongs in the PRD — a consumer is depending on it, so it is a commitment rather than a detail. If no, it belongs in the design doc, and putting it in the PRD takes a decision away from the person best placed to make it.
Run it on a few:
| Line | Would a consumer notice? | Belongs in |
|---|---|---|
Returns 409 on a duplicate submission | Yes | PRD |
| Duplicate detection uses a unique index | No | Design doc |
| Responds within 400ms at p95 | Yes | PRD |
| Achieved with a read replica | No | Design doc |
| The webhook retries 5 times over an hour | Yes | PRD |
| Retries run on a queue rather than a cron | No | Design doc |
| Rows are soft-deleted and purged after 30 days | Yes, at 30 days | PRD |
| The purge job runs at 03:00 | No | Design doc |
The test does most of the work. Where it gets interesting is the handful of lines that seem to fail it.
What a technical PRD specifies
Seven things, and a spec with all seven rarely needs a meeting to interpret.
The contract. Inputs, outputs, shapes, required versus optional. Field names matter here in a way they never do in a consumer-facing spec, because a consumer writes code against them.
Semantics. What each response means, not only its code. 202 says accepted — accepted for
what, and how does the caller find out whether it worked?
Failure behaviour. Which failures are possible, which are retryable, and what the caller should do. This is the error-state question in its machine-readable form, and it is skipped just as often.
Idempotency and ordering. Can the same call safely repeat? Do events arrive in order, and if not, is that guaranteed anywhere? Silence here is read as "yes" by every consumer and is almost never true.
Limits. Rate, page size, payload size, concurrency. Unstated limits are discovered in production by whoever hits one first.
Compatibility. What is versioned, what may change without notice, how deprecation is communicated and over what window. The only section of a technical PRD that gets more valuable with age.
Observability. What must be measurable — not which dashboard, but which questions the system has to be able to answer. "We must be able to see the failure rate per consumer" is a requirement; picking the metrics backend is not.
What stays out
Storage engine and schema. Index strategy. Queue versus cron versus synchronous. Language, framework, library. Caching approach. Deployment topology. Thread pools, connection limits, retry backoff implementation.
Every one is a decision that depends on the codebase, the team's operational experience, and things that will be true in six months and are not true now. None is observable to a consumer.
The three that look blurry
Each of these is a how with a what hiding behind it. Finding the what is the whole job.
"Must use Postgres." Ask why. If the answer is data residency, the requirement is data stays in this region. If it is an existing operational commitment, the requirement is no new datastore this quarter. Write that, and note Postgres as the expected answer. The spec then survives the day someone finds a better one, and — more importantly — the reviewer can evaluate the actual constraint rather than a technology preference.
"Must be asynchronous." The requirement underneath is usually a latency budget, or the ability to survive a slow dependency without failing the caller. Async is one implementation. Say "the caller receives a response within 300ms regardless of downstream latency" and you have specified the property while leaving the mechanism open.
"Must cache." Same shape. The requirement is a latency number and possibly a staleness tolerance — "data may be up to 60 seconds stale" is a genuine product decision with user-visible consequences, and it is the part that belongs to you. How the staleness is achieved does not.
The pattern is consistent: a stated how usually has a more durable what behind it, and the translation takes one question. It is also the difference between a spec engineers argue with and one they argue inside.
Why the discipline matters more here
Two reasons specific to technical work.
Contracts are sticky. A consumer-facing screen can be redesigned next quarter; a published API shape has consumers who will still be sending that payload in two years. Getting the what right matters more, and getting the how wrong costs less, which is exactly the opposite of the intuition that makes PMs over-specify technical work.
And credibility is asymmetric. A gap in a technical PRD reads as a question. A prescribed implementation reads as a PM designing a system they do not operate — and once that impression lands, the rest of the document gets read with suspicion rather than trust.
Migrations are the special case
Migration specs are technical PRDs with an extra state, and it is the one they skip.
Most describe the old behaviour and the new behaviour. The risk is entirely in the middle — the period where both exist. That section needs: what is dual-written and for how long, how the backfill is ordered and what happens if it stops halfway, what a consumer still on the old contract sees, how you verify the two agree before cutting over, and what "roll back" means once new-format data exists.
A migration PRD without the middle has specified the two easy states and omitted the only one that can hurt you.
If you are starting one, the Technical / API PRD template has the contract sections laid out with the review rubric attached, so the gaps are visible while the document is still cheap to change.
FAQ
What is a technical PRD? A spec for a feature whose users are other systems. It states observable behaviour — contract, semantics, failures, guarantees.
How does it differ from a design doc? The PRD says what a consumer can rely on; the design doc says how the service delivers it.
Can it name a technology? Check what is hiding behind the name first. Usually there is a more durable requirement to write instead.
What do migration specs miss? The middle — the window where old and new both exist, which is where all the risk is.