Writing a Use Case: The Main Flow Is the Easy Half
The main flow of a use case writes itself. A worked returns case where the exceptions take three times the space, with the source of each one named.
Open any requirements pack and find the use case. The main flow runs six or seven steps, each a clean sentence, and you agree with all of them before you reach the bottom. Then scroll. Alternative flows: none listed. Exceptions: "the system handles errors and informs the user." Somebody spent an afternoon on that page, and the afternoon went into the half nobody was going to argue about.
A use case is a description of how an actor and a system interact to reach a goal, written as a numbered sequence of steps together with every way that sequence can go differently. The second half of that sentence is where the work is, and it is the half that arrives empty.
In short
- The main flow is the version everyone already agrees on, which is why writing it feels productive and costs you nothing.
- The value sits in the branches: the variations that still reach the goal, and the exceptions that do not.
- In the worked case below the main flow is six steps and the exceptions run to fourteen, roughly the proportion I now expect to see.
- Every exception should carry a source. Published rule, observed complaint, or your own inference labelled as one. An exception with no provenance is a guess with a delivery date attached.
The worked case here is returns and complaints at a mid-size online retailer, built from public sources only: the published returns policy, the help centre articles, and ten public complaint threads I selected myself. No engagement, no client, no interviews, no workshop, and nobody at that company was asked about anything. Where a branch comes from my own reasoning, the document says so on its face.
Why does nobody argue about the main flow?
Because the main flow is the story the business tells about itself: the version on the marketing page, in the onboarding deck, in the sponsor's head when they approve the budget. Everyone is carrying the same picture of it, so reading it back produces nods rather than questions.
Disagreement needs a branch. It appears the moment you ask what happens when the warehouse says the item came back used and the customer says it did not. There is no shared picture of that, because most people in the room have never had to hold it.
A thin exception section costs you three things, all after you have left the document. The developer invents the missing branch at the keyboard, choosing whatever is cheapest to build. The tester cannot test a case with no stated outcome, so it ships untested. And the stakeholder who would have caught the gap never sees it on a page.
UC-03: Return an item bought online
Read this for the proportion before you read it for the content.
Actor. Customer (primary). Supporting: returns handling system, carrier, warehouse, payment provider.
Goal. Send back a delivered item and get the money back to the instrument that paid for it.
Precondition. The order is delivered, the customer can identify it, and the item is not in a category the published policy excludes from return.
Trigger. The customer decides to send the item back.
Main flow
- The customer opens the delivered order and selects the line to return.
- The customer picks a return reason from the list and submits the request.
- The system checks the line against the return rules and accepts the request.
- The system issues a return id and a shipping label.
- The customer sends the item back; the warehouse receives it and records its condition as matching the stated reason.
- The system refunds the line to the original payment method and closes the return with an outcome and a reason code.
Postcondition (success). The item is back in stock or written off, the refund is recorded against the paying instrument, and the return closes with a reason code that can be counted later.
Alternative flows (the goal is still reached)
- 2a. The customer chooses an exchange. Step 6 issues a replacement order, and the return closes only when the replacement is dispatched.
- 4a. The customer has no printer and uses a drop-off point with a code instead of a label. The return id is unchanged.
- 6a. The order was paid partly with store credit. The refund splits across instruments in proportion, and the split is shown before it is made.
Exceptions (the goal as stated is not reached)
- 1a. The order is outside the return window published in the policy. Refused, showing the window and the delivery date, with the statutory withdrawal right stated separately so the refusal cannot swallow it.
- 1b. The line is in a non-returnable category. Refused, naming the category and the clause rather than showing a generic block.
- 1c. The person holding the item is not the account holder: gift, guest checkout, someone acting for a relative. Out of scope for release 1, with a route to support and the exclusion written into the scope section, not left implied.
- 3a. The item arrived damaged or the wrong item was sent. The request leaves this use case for the complaint flow, where the customer does not pay return shipping.
- 3b. The parcel never arrived. There is nothing to return, so this use case does not apply and the non-delivery flow owns it.
- 4b. The label is issued but never reaches the customer, so the return sits with no movement. After the period in the policy it goes to a named owner who re-issues, and the customer hears from someone before the window closes.
- 5b. The parcel is lost in transit. The customer holds proof of postage and no item exists to inspect. The carrier claim runs in parallel and the refund decision does not wait for it.
- 5c. The warehouse records a condition that does not match the stated reason: used, missing parts, a different item in the box. The return stops. A named owner decides, the customer is told what was found, and the evidence is recorded with the decision.
- 5d. Nothing arrives by the deadline. The return closes as not received, with one notice beforehand and a route to reopen it.
- 5e. Two lines arrive under one return id, or one id arrives split across two parcels. Each line is resolved on its own; the return closes when the last one has an outcome.
- 6b. The paying card has expired or the account is closed. The refund cannot follow the original instrument, so it needs an alternative and a check that the alternative belongs to the same person.
- 6c. The provider declines the refund. That is a failed refund, not a completed return, and it needs an owner, not a retry loop.
- 6d. The line was bought under a discount applied across the whole order. Refunding it changes what the rest qualified for. Either the discount is recalculated or the rule says it is not, but somebody has to say which.
- 6e. A refund already exists for this line. The second request is refused, and the refusal names the first so nobody has to phone anyone to find out why.
Count the lines. Main flow six, alternative flows three, exceptions fourteen: about three times the space, and not padding. Every exception ends in an outcome you could write an acceptance criterion against, which is a harder standard than listing what could go wrong.
Where does each exception come from?
Every branch traces to one of four places. P is the published policy, H the help centre articles, T the ten complaint threads I picked, I my own inference.
| Exception | Source | What it rests on |
|---|---|---|
| 1a window, 1b category | P | Written rules in the policy |
| 1c not the account holder | T, I | Threads show gift and guest cases; the scope call is mine |
| 3a damaged or wrong item | P, H | Policy names it, the help centre routes it separately |
| 3b never arrived | H, T | The help centre separates non-delivery from returns |
| 4b label never received | T | Threads where the return stalls before it starts |
| 5b lost in transit | T | Threads with proof of postage and no item |
| 5c condition dispute | T, H | The longest threads; the help centre explains inspection |
| 5d nothing arrives | I | Nothing public describes it; the wait needs an ending |
| 5e split or merged parcels | I | One id and many lines cannot both be atomic |
| 6b instrument gone | I | Time passing between purchase and refund |
| 6c refund declined | I | Any external provider call can fail |
| 6d discount across the order | I | Pricing rule and line-level refund cannot both hold |
| 6e duplicate refund | H | The help centre asks customers not to file twice, so they do |
Three of the ten threads I read ended in a condition dispute. That is a count of ten threads I picked myself, not a rate, and it is my own tally from those threads rather than a figure carried in the published case, which counts a different thing: four of the ten ended with nobody owning the case at all. Enough to know the branch exists, nowhere near enough to know how often.
The rows marked I are the interesting ones. Five of the fourteen rest on nothing public at all - 5d, 5e, 6b, 6c and 6d - and they came from reading the main flow one step at a time and asking what else can happen here. No interview would have produced them either: they are the cases nobody owns, which is why they end up unowned in the live process too.
The blank version
Copy this. The hints in square brackets are the parts that go missing first.
UC-[nn]: [verb + object, from the actor's point of view]
Actor: [primary actor, then supporting systems]
Goal: [what the actor has when this succeeds]
Precondition: [what must already be true; if you cannot check it, it is a step]
Trigger: [the event that starts this, not the screen it starts on]
Main flow
1. [actor does something]
2. [system responds]
6. [end state in business terms, not a screen message]
Postcondition (success): [what is now true, and what can be counted]
Alternative flows [same goal, different route]
- [step]a. [variation] -> [where it rejoins the main flow]
Exceptions [goal not reached; expect two to four per main-flow step]
- [step]a. [what goes wrong] -> [outcome, and the named owner who holds it]
[source: policy / observed / inferred]
Out of scope on purpose: [the exception you excluded, and why]
Open questions: [question, owner, date it is needed by]
The last two lines are the ones I used to leave off. An exception you excluded on purpose is a decision. An exception you never noticed is a defect with a release date on it, and from the outside the two documents look the same.
Which questions generate the exceptions?
I do not find branches by staring at the flow. I run these against every step and stop when a question produces nothing twice running.
- Is the actor who the system thinks they are? Gifts, guest checkout, someone acting for a relative.
- Does the thing still exist in the state this step assumes? Already refunded, cancelled, or returned once.
- What if the step happens twice? Double submit, two parcels, a retry after a timeout.
- What if it never happens? Every wait needs an ending: a period, an owner, and one notice before it closes.
- What if it happens partly? One line of three, a split payment, a parcel with an item missing.
- What if the other side says no? The provider declines, the carrier loses it, the warehouse disagrees.
- What does the law say where the policy says otherwise? Published rules do not override statutory rights, and the refusal message is where that goes wrong.
- What if the actor changes their mind halfway? Started a return, now wants an exchange; posted the parcel, now wants to cancel.
- When the flow stops, who is holding it? If the answer is a shared inbox, the case has just stopped being anybody's problem.
Question 9 is the one that changes documents. Every branch that ends without a name is a branch that will end without a decision.
Take a use case you have already written. Count the main-flow steps, count the exceptions, and if the second number is not the larger one, you wrote the easy half and stopped. Run the nine questions down the flow and watch the proportion move.
The returns case this use case is written against, with the register its criteria feed, is the worked case on this site. The pack carries the process models and the register rather than a use case document, so the flow above is the same material laid out the other way. That register is one of the six artifacts a reviewer looks for, and the outcomes in the exception list are where its acceptance criteria come from.
Read next
Acceptance Criteria That Survive a Sprint Review
What an acceptance criterion actually is, six weak ones shown as they arrived and as they went out, and the three object
As-Is Before To-Be: Modelling the Process That Actually Runs
Two models of the same returns process side by side, and the table of differences between them, with the column most peo
Get the Proof Pack
Six blank templates and one worked case. Free, one email. The scorecard is a separate file and needs none.
Send it to meAll field notes · The portfolio guide · More in The Case File