Use Cases vs User Stories: When to Pick Which
- Shawn West
- Apr 11
- 12 min read
Updated: Aug 17
Nobody ever failed a project by picking the wrong requirements template. They failed because the format they picked never asked them to write down the ten ways the transaction can end badly. Use cases and user stories differ in one structural respect — what each forces you to enumerate — and that difference has a number attached to it. Here's the number, the feature written both ways, and the decision one of them made possible.
The argument always starts the same way. Someone brings a story to refinement with thirty-one lines of acceptance criteria stapled to it, and a senior analyst says what everyone is thinking: this isn't a story anymore. The room then divides along the usual fault line — use cases are waterfall residue, stories are a licence to skip thinking. Both sides argue about culture. Nobody argues about the feature.
That thirty-one-line story is not a process-ideology problem. It is a signal, and it is measurable. The format was chosen before anyone counted what the feature contained.
What each format forces you to write down
Strip both formats to their skeletons and one difference survives.
A user story is, by design, not a requirement. Ron Jeffries' 2001 formulation — Card, Conversation, Confirmation — makes this explicit: the card is a token reserving a place for a discussion, not a specification of behaviour. Mike Cohn's User Stories Applied takes the same position; the brevity is the feature. The canonical template has exactly three slots — role, capability, benefit — and none of them is a slot for a failure. "As a customer, I want X, so that Y" cannot syntactically express "and when the card issuer declines the reversal because the authorization is 200 days old, here is who decides what happens next." The format's silence on failure is not an oversight; it is the design intent, on the theory that the conversation will surface it.
A use case is built from the opposite premise. Alistair Cockburn's Writing Effective Use Cases structures the artifact as a main success scenario plus extensions — the conditions under which the flow deviates — and his precision levels treat those extensions as the expensive part: level 3 enumerates the extension conditions, level 4 writes what happens in each. His instruction is to brainstorm and exhaustively list the conditions the system can detect and must handle. Which makes the main success scenario the cheap part: everyone in the room already agrees on the happy path, it takes four minutes to write, and it produces no new information.
So the honest framing is not "documentation-heavy versus lightweight." It is: a use case is an enumeration engine with a narrative wrapper, and a user story is a conversation placeholder that reports success only. Everything else — length, formality, who writes it, which methodology it belongs to — is downstream of that. INVEST criteria for better user stories covers what a good story owes you before a sprint, but INVEST tests a story's shape, not whether the feature underneath has more branches than a story can hold.
Run this today: pull the last five stories your team shipped. For each, count the distinct non-success conditions written down anywhere — story, AC, ticket comments, test names. Not "we discussed edge cases." Written down. If the median is under two and the features weren't trivial, the enumeration didn't happen; it just didn't happen visibly.
One fork, walked: the same refund, written twice
The following is an illustrative composite drawn from patterns common in retail and payments work. The identifiers, percentages, and figures are illustrative, not measured.
A mid-market outdoor-gear retailer — call the platform Halden — was rebuilding returns. One feature: refund a returned item. Here is the story that entered the sprint.
HAL-412. As a customer, I want a refund for an item I've returned, so that I get my money back promptly. AC: Given a delivered order, when the returned item is received and inspected at the warehouse, then the refund is issued to the original payment method within three business days and the customer receives a confirmation email.
That is a good story by any standard you'd apply — independent, negotiable, valuable, small, testable, with a clean Given/When/Then. It would pass refinement in most teams on the planet.
Now the same feature as a use case. The main success scenario is six steps and takes four minutes: customer requests return → system validates eligibility → warehouse receives and inspects → system computes refund amount → system reverses the payment → system notifies customer. Nothing there anyone would dispute.
The extensions took ninety minutes, and this is what came out.
Ext. | Condition | Who owns the decision |
2a | Request falls outside the published return window | Merchandising policy |
3a | Received item doesn't match what shipped (wrong SKU, missing parts) | Warehouse ops |
4a | Order was paid across two tenders — card plus store credit | Finance |
4b | Original card is expired, closed, or reported stolen | Unowned |
4c | Gateway's refund-against-original-authorization window has elapsed | Unowned |
5a | Item's removal drops the order below a spend-threshold promo | Merchandising |
5b | Refund breaks the free-shipping threshold the order qualified under | Merchandising |
6a | A chargeback has already been filed on the same order | Fraud/finance |
6b | A partial refund was already issued against the same line | Finance |
7a | Refund exceeds the amount captured on that shipment (split capture) | Engineering |
Ten conditions. Read HAL-412 again and find where any of them would live. They can't live in the "so that" clause, and they don't fit in the Given/When/Then, because that structure has one when and one then.
Two rows were the expensive ones, and they are the two marked unowned. Halden's gateway capped refunds against the original authorization at 180 days — a limit most gateways impose in some form; check yours rather than assuming. Their return policy permitted extended-warranty returns well past that. So for a slice of refunds, the acceptance criterion on HAL-412 was not merely incomplete — it was false. "Issued to the original payment method" was not a thing the system could do, and no test written against that story would ever have said so, because tests are written against the then clause and the then clause was wrong.
Here is the fork. The story version ships, and the gap surfaces in production as a support queue: refunds silently failing at the gateway, no error shown to the customer, agents issuing store credit at whatever value they judged fair. That last part is the real cost — an unowned decision doesn't disappear, it gets made by whoever stands closest to it, inconsistently, with no audit trail. The engineering fix is two days; reconciling months of ad-hoc agent-issued credit is a finance project.
The use case version does not ship faster. What it does is turn 4b and 4c into agenda items before the sprint. Halden's actual decision, made in a two-hour session: HAL-412 stayed in the sprint but its AC was rewritten to cover only refundable tenders; 4b and 4c were routed to a documented manual finance queue with a named owner and a 5-business-day SLA; 5a and 5b went to merchandising as policy questions with a date; and the fallback-tender rule was written down as a policy artifact rather than left to agent judgment. The feature shipped in the same sprint. The difference is that the deferrals were chosen, with owners and dates, instead of discovered by a customer.
Run this today: take the highest-value item in your sprint and write only its extension conditions — skip the main flow, everyone knows it. Mark each with an owner and count the ones you can't assign. Unowned conditions are your real scope risk, and they're invisible in story format.
The discovery move
The question that separates these two outcomes is not "should this be a use case?" It is asked during elicitation:
"List every state this transaction can be left in that isn't 'done', and name who decides what happens in each."
Three parts, all load-bearing. Every state that isn't done forces generation rather than validation — you aren't checking a list, you're producing one, and producing it is the part people skip. Left in catches the stuck states pure error-handling misses: a refund that reversed one tender and not the other isn't an error, it's a half-finished transaction someone must resolve. Who decides is the one that hurts, because it exposes conditions that aren't engineering problems at all. 4b isn't a bug. It's an unmade policy decision about giving a customer money by a route they didn't pay by, with a fraud surface attached, and no engineer should be making it inside an if block at 4pm.
Halden's failure was not a coding failure and not a testing failure — every test that existed passed, against criteria that were wrong. It was a question nobody asked while capturing the requirement, and the format made the omission invisible, which is exactly what a format that reports only success will do. Requirements elicitation techniques that work covers which instruments surface which class of unstated constraint.
Run this today: ask that question about one in-flight feature, with someone from operations or finance in the room. Count the conditions that turn out to belong to a non-engineering owner. In flows involving money, identity, or permissions, that count is never what the team expected.
Branch density — the actual selection criterion
Here is the diagnostic that replaces the culture argument. Before choosing a format, count the distinct ways the flow can end in something other than success — not implementation branches, but outcomes a human would recognize as different.
Distinct non-success conditions | What to reach for | Why |
0–2 | User story, AC only | The conversation genuinely covers it; a use case is ceremony with a table of contents |
3–6 | Story plus an explicit extension list | The story stays the delivery unit; the list stops the branches from living in one person's head |
7+ | Use-case-shaped enumeration, whatever you call it | At this density the branches interact, and interaction is what unstructured discussion loses |
The thresholds are judgement calls, not measurements — a forcing function rather than a rule. What matters is that the count is observable and can be produced in twenty minutes by someone who knows the domain, which is more than can be said for "does this feel complex?"
The final row exists because above roughly seven conditions the branches stop being independent. Extension 4a (split tender) and 6b (prior partial refund) are individually simple; the case where both are true — a partially refunded order paid across two tenders — is a distinct behaviour nobody specifies, because it appears in neither list. A structured enumeration makes those pairwise interactions visible on the page. Conversation doesn't, because conversation is linear and interactions are combinatorial.
Note what the count is not correlated with: feature size, story points, or team maturity. A three-point feature that touches money can carry ten conditions; a twenty-point dashboard carries one. Sizing and branch density are orthogonal, which is why story points tell you nothing about format.
Run this today: count non-success conditions for the next three items entering refinement and write the number on the ticket, before anyone argues about format. The argument tends to evaporate once the number is visible — the disagreement was never about templates, it was two people holding different mental counts.
What each format hides, structurally
User story | Use case | |
Optimized for | Deferring detail until it's cheapest to gather | Enumerating what must be handled before design |
Native unit | A negotiable slice of value | A goal-level interaction with an actor |
Where failure lives | Nowhere in the format; in AC or in a conversation | First-class: numbered extensions |
Structurally hides | Branch interactions, unowned decisions, false AC | The cost of the happy path; what's negotiable |
Cost when wrong | Discovered in production by a customer | Weeks specifying flows that were never in doubt |
Fails when | Failure modes are the feature | Applied to a one-path feature to satisfy a process |
The right-hand failure mode is real and burns more calendar time than teams expect. Fully-dressed use cases for a settings toggle aren't rigour; they're a document whose entire information content is the title.
Run this today: open your last use case and delete the main success scenario. If what remains still communicates the requirement, the artifact earned its keep. If the document collapses, you wrote a narrative, not an enumeration.
The hybrid that actually works
Most teams should not choose. They should keep the story as the unit of delivery and borrow the enumeration.
The mechanism is one rule with teeth: a story whose extension count exceeds three cannot enter a sprint without a numbered extension list attached, each extension carrying a named owner. Not a use case document — a list, in the ticket, with numbers. The numbering matters more than it sounds like it should: numbered extensions get referenced in test names, commit messages, and support-triage macros; bullet points do not.
That rule buys three things a story alone does not: a visible count for planning, a home for the conditions that turn out to be policy rather than code, and test names that map to conditions instead of to the happy path. Where an extension is universal handling — every payment flow must surface a gateway failure rather than swallow it — it belongs in Definition of Done instead of being repeated per story; definition of done vs acceptance criteria draws that line. Where it's feature-specific, it's acceptance criteria.
The borrow runs the other way too. Use cases are weak on why, and job stories — "when [situation], I want to [motivation]…" — carry the triggering circumstance better than either format. "When…" is also a decent enumeration prompt: it invites you to list the other whens.
Run this today: add the extension count as a required field on your ticket template. One integer. Watch what happens to refinement conversations in two weeks — the field is doing the same work as the ninety-minute session, at a hundredth of the cost.
The exception: when branch density lies
The count is a good instrument, and there are four situations where it misleads.
The branches are all the same shape. Forty field-validation rules is a high count and a terrible use case. That's a decision table — a grid of inputs and expected responses. Use-case extensions are for conditions that change who does what next; homogeneous input validation changes nothing but a message string. Count distinct resolutions, not distinct triggers.
You don't know the domain yet. Enumerating extensions for a workflow you're still discovering produces fake precision — a confident list of the wrong conditions, worse than an honest gap because it looks finished. In exploratory work, a thin story plus a short-lived prototype surfaces real conditions faster than a room of people imagining them. Enumerate once the flow has survived contact with users.
The flow is being replaced within the year. Extensions are the costliest part to maintain — every policy change touches several at once. Enumerating a system you're decommissioning is archaeology.
Low branch density but an external reader. This one runs the other way — the exception to skipping the use case. Regulated, safety-critical, and contractually-specified work sometimes demands the structured artifact for a two-branch flow, because "we discussed it in refinement" is not a submission. ISO/IEC/IEEE 29148:2018 treats use cases as a legitimate requirements representation and expects individual requirements to be verifiable; if someone will audit the representation, the representation is a deliverable regardless of the count.
None of these restores "it depends." Three lower the format's value at high counts; one raises it at low counts — and in all four you can name the condition that moved it, which is the difference between a judgement and a shrug.
Run this today: wherever you're about to skip enumeration, write one sentence naming which of the four exceptions applies. If you can't name one, you're not making an exception — you're just not counting.
The Monday diagnostic
Take the highest-consequence item in your current backlog and spend twenty minutes:
Write the main success scenario in six steps or fewer. If it takes longer than five minutes, the item is two items.
Enumerate every condition under which those steps don't complete. Number them. Stop when you're repeating yourself, not when you're tired.
Put an owner on each. Engineering, ops, finance, legal, merchandising, compliance. Unowned rows are the finding.
Count the rows and pick the format from the count. Under three, the story was right. Over seven, you needed the enumeration whatever you decide to call the file.
Re-read the acceptance criteria against the list. You are hunting the Halden failure — not a missing criterion, a false one. An AC asserting an outcome the system cannot always produce is worse than no AC: it converts an open question into a passing test.
Step five is worth doing even if you skip the rest. A missing requirement gets found eventually, by someone, in a meeting. A wrong one gets found by a customer, because everything upstream of them agreed.
The format debate persists because both sides defend something true: stories are better at deferring detail until it's cheap to gather, use cases are better at making sure the detail exists. Those aren't competing philosophies — they're answers to different questions about the same feature, and the feature already knows which one applies. It has a number. Count it before the argument starts and there won't be one.
Sources
Alistair Cockburn, Writing Effective Use Cases (Addison-Wesley, 2000) — main success scenario plus extensions; precision levels for enumerating extension conditions and extension handling.
Ivar Jacobson, Object-Oriented Software Engineering: A Use Case Driven Approach (Addison-Wesley, 1992) — the origin of use cases as a requirements structure, first presented at OOPSLA in 1987.
Mike Cohn, User Stories Applied: For Agile Software Development (Addison-Wesley, 2004) — stories as placeholders for conversation rather than complete specifications.
Ron Jeffries, Essential XP: Card, Conversation, Confirmation (2001) — the three-part definition of a story.
Bill Wake, INVEST in Good Stories, and SMART Tasks (2003) — the INVEST criteria for story quality.
ISO/IEC/IEEE 29148:2018, Systems and software engineering — Life cycle processes — Requirements engineering — requirements representations including use cases, and the verifiability characteristic of a well-formed requirement.


