Thinkr

Craft

The Edge Cases Your PRD Is Missing

Five lenses for finding the edge cases a spec leaves out — boundary, sequence, permission, concurrency, absence — and what to write once you find one.

Galang Aulia · 6 min read
Craft

An edge case is not an unlikely event. It is an unconsidered one — a condition your requirement is technically true for, but was never written for. That distinction matters, because it explains why edge cases are not found by imagining unusual users. They are found by interrogating the assumptions inside a sentence you already wrote.

Below is the pass I run: five lenses, applied to each requirement in turn. It is deliberately mechanical, because the cases you miss are by definition the ones your imagination does not volunteer.

Why they go missing

Requirements are written in the success case, because that is the case you were thinking about when you decided to build the thing. "The owner invites a team member." Every word of that is about things going right, and nothing in it is wrong — it is just radically incomplete, and it reads as finished.

That last part is the real problem. A gap you can see looks like a gap. A gap phrased as a complete sentence looks like a requirement, which is why re-reading your own spec surfaces so little. You are not looking for something missing; you are agreeing with yourself.

The five lenses

Take one requirement. Run all five. Move to the next requirement.

1 · Boundary — what happens at zero, one, and the maximum

Every quantity in your spec has ends, and behaviour at the ends is almost never stated.

Ask: what happens at zero of this thing? At exactly one? At the limit? Past the limit?

"The dashboard shows the team's active projects."

Zero projects — is that an empty state with guidance, or a blank panel? One project — does a grid built for many look broken with one? Two hundred — is there pagination, and what is the sort order when nobody chose one? These are three different screens, and the requirement as written implies one.

Boundary is the highest-yield lens by a distance. Most missing screens live here.

2 · Sequence — what if this happens out of order, twice, or not at all

Requirements imply an order. Users do not read the requirement.

Ask: what if the steps happen backwards? What if a step happens twice? What if the user abandons halfway and returns tomorrow?

"After payment, the participant is enrolled in the programme."

What if payment succeeds and enrolment fails — has the user paid for nothing? What if they submit twice, from two tabs? What if they return after the programme has started? Each is a real state someone will occupy, and none is described.

Sequence gaps are the ones that produce support tickets rather than bug reports, because the system is technically working.

3 · Permission — who cannot do this, and what do they see

Specs describe what the actor can do. They rarely describe the actor who cannot.

Ask: who is not allowed here? Do they see the control disabled, or not at all? What happens if their permission is revoked while they are on the page?

"Admins can export the participant list."

What does a non-admin see — a hidden button, or a visible one that errors? What about someone who was an admin when the page loaded and is not one now? What about an admin of a different organisation who has the URL?

Hiding versus disabling is a product decision with a real consequence, and leaving it unstated means it gets decided by whoever writes the component.

4 · Concurrency — two actors, one object, the same moment

The quiet one. Rare enough to skip, expensive enough to matter.

Ask: what if two people act on this at once? What if the thing is modified while being read? What if it is deleted mid-edit?

"An owner can change a member's role."

Two owners demote each other simultaneously — does the workspace end up with none? One owner removes a member while that member is submitting a form. Someone edits a document another person just deleted.

You will not catch every concurrency case, and you should not try. Name the ones where the failure is silent or destructive, and let the rest surface in testing.

5 · Absence — the thing is gone, expired, or unreachable

Your requirement assumes its subject exists. Frequently it does not.

Ask: what if the record was deleted? The link expired? The integration disconnected? The upstream service down?

"The invitation link takes the user to the workspace."

Deleted workspace, revoked invitation, expired link, already-used link, user already a member, user signed into a different account. Six states, all reachable from one sentence, none of them described.

Absence is where third-party integrations quietly ruin a launch: the requirement assumes the integration responds, and never says what the product does when it does not.

Running the lenses on one requirement

Take a plain line:

"Users can upload a profile photo."

LensWhat it surfaces
BoundaryMaximum file size? Minimum dimensions? What about a 40MB TIFF?
SequenceUpload succeeds, crop is abandoned — is the old photo gone?
PermissionCan an admin change someone else's photo? Should they?
ConcurrencyTwo devices upload at once — which one wins?
AbsenceThe CDN is down. Does the form fail, or queue, or silently drop it?

Nine questions from ten words, and every one has a user-visible answer. This is why the pass is worth running even on requirements that feel too simple to need it — especially on those, because simple-looking requirements are the ones nobody reviews carefully.

What to write once you find one

Finding a case is half the job. A case written badly is not covered, it is mentioned.

Write the condition, not the worry. "Handle expired invitations" is a note to yourself. "An expired invitation link shows This invitation has expired with a Request a new one action that notifies the workspace owner" is a requirement.

Say what the user sees. Every edge case has a UI consequence, even if that consequence is deliberately nothing. If you cannot say what appears on screen, you have not finished the case.

Decide, do not defer. "TBD with engineering" in a spec means the decision will be made under time pressure by whoever hits it first, and it will be made to unblock a ticket rather than to serve a user.

Put it next to the requirement it belongs to. An "Edge cases" appendix at the end of a PRD is where cases go to be skipped. Attach each one to its own requirement, so the person implementing that line cannot miss it.

Where this sits in a review

This pass is Thinkr's seventh critique pass — the Edge Case & QA Drill — and it is one of the two that catches the most in practice. The other is Engineering Readiness, which is downstream of it: a requirement with uncovered edges cannot be estimated honestly, because the estimate is a guess about work nobody has scoped.

Run the five lenses before your spec goes to review, not after. What survives them is what a reviewer's time is actually worth spending on.

FAQ

What is an edge case in a PRD? A condition your requirement is true for but was not written for. Unconsidered, not unlikely.

How do you find them systematically? Five lenses per requirement: boundary, sequence, permission, concurrency, absence. Brainstorming finds what you can imagine; lenses find what you cannot.

How many should a PRD cover? Enough that an engineer never has to invent behaviour. If they would have to guess, it belongs in the spec.

PM or QA? QA will find them — in staging, which is the most expensive place to discover a requirement. The PM's job is the structured pass beforehand.

New posts and release notes. No spam, unsubscribe anytime.

Stop shipping foggy PRDs.
Start the critique loop.

Three minutes to sign up. No credit card. Cancel by closing the tab.

Start freeSee pricing