RequirementsGENERALSTAGE-SPECIFICILLUSTRATIVE

Requirement Discovery

"Need checkout" is one requirement written down and a dozen hidden inside it. Discovery is asking "what if" of the sentence — payment fails, the user refreshes, the backend crashes after the charge, the product sells out — until the hidden ones have names and each can be tested.

The situation, the reflex, and why it stalls

Every lesson starts where being stuck starts: someone has a problem, and the first move that comes to mind feels like progress.

The question

You are handed "need checkout" and nothing else. How do you find the requirements that are not written down, and how do you know when you have found enough to start?

The situation

The ticket says "Checkout: customer pays for the cart and gets an order." Everyone nods; it is obvious. You start building it and on the second afternoon you realise you do not know what the page should do when the payment provider takes a long time to answer, and nobody in the room knows either.

The reflex

Build the obvious version. Cart → pay button → call the provider → create the order → show a confirmation. It is what every tutorial shows, it is what the ticket literally says, and having it on screen feels like most of checkout being done.

Why it stalls

The obvious version works exactly once, on the author's machine, with a card that succeeds. Every requirement it did not discover arrives later as a bug report — the double order from a double click, the paid-but-orderless customer from a crash — and each one is now a change to code that was shaped without it.

What the reflex produces — and fails to produce
  • The obvious version works exactly once, on the author's machine, with a card that succeeds. Every requirement it did not discover arrives later as a bug report — the double order from a double click, the paid-but-orderless customer from a crash — and each one is now a change to code that was shaped without it.
  • Requirements that were never named cannot be tested, prioritised or postponed. "Handle failures" is on nobody's list, so it is on nobody's plan, so it is discovered by a customer.
  • The diagram gets drawn instead. Boxes for cart, checkout, orders, payment; arrows between them. It looks like understanding and contains none of the questions — a diagram of the happy path is a picture of the ticket.
  • When the stakeholder is finally asked "what should happen if the payment succeeds but we crash before saving the order?", the answer is "that can happen?" — and the conversation that should have started the work starts in week three.
ProblemUnderstandRequirementsConstraintsUnknownsDecompositionSmallest StepModelExperimentObserveDebugLearnIterate

The move

Precisely enough to apply it to a problem you have never seen — not a slogan.

  • Treat the sentence you were given as the *visible* requirement and assume the rest are hidden inside it. Hidden requirements are found by asking "what if" at every point where the world could differ from the happy path: an external system answers slowly, wrongly or not at all; the user does something twice, or leaves, or comes back; the data changed between two steps; our own process dies in the middle.
  • Walk the workflow step by step and at each step ask the four questions: what if this fails, what if this repeats, what if the state has changed since the previous step, what if we crash right here. Each question that has no obvious answer is a requirement you have just discovered, and it is written as a sentence with a testable outcome, not as "handle errors".
  • Sort what you found. Some discovered requirements are V1 — a payment must not be taken twice; some are explicitly deferred with a reason — partial refunds; some are questions for the stakeholder — what does the customer see while we wait for the provider? The sorting is the deliverable: a list with three columns and a reason in each cell.
  • Stop when the next step of building would not be changed by any remaining question. Discovery is not finished when the list is complete — it never is — it is finished when you can build the first slice without guessing about anything that would reshape it.

What "need checkout" hides

The board below is the visible requirement taken apart. On the known side is what the sentence actually says; on the unknown side is each "what if" rewritten until it is something the stakeholder could answer or an experiment could settle. Notice that every vague entry started life as a feeling — "payments are scary" — and ended as a question with a verb.

The assumed column matters as much as the other two. "One currency" is not a requirement anyone stated; it is a decision the team is making by not making it, and writing it down is what lets the design change on purpose later instead of by accident.

Checkout, after an afternoon of "what if"
known
  • A customer with a non-empty cart can pay and receive an order.
  • The provider is outside our system: it can be slow, wrong, or down, and we do not control when it answers.
  • Stock is finite and other customers are buying at the same time.
assumed
  • ~One currency and one payment provider in V1 — written down so that adding a second changes the design deliberately.
  • ~A customer checks out one cart at a time; concurrent checkouts by the same customer are not a V1 case.
unknown → question → experiment
  1. ? What if the payment fails?

    becomes For each way the provider can answer — declined, error, timeout, no answer — what state is the checkout left in, and what does the customer see?

    experiment In the provider's test mode, trigger a decline, an error and a forced timeout against a bare endpoint and write down what our code receives in each case.

  2. ? What if the user refreshes?

    becomes If the customer reloads while we are waiting for the provider, does the page show the in-flight checkout, an empty cart, or a second Pay button — and which one do we want?

    experiment Give the checkout an id before Pay is clicked; reload mid-request and see whether the page can find it.

  3. ? What if it succeeds but we crash?

    becomes When the provider has charged the card and our process dies before the order row exists, how do we find out, and who reconciles the payment with a missing order?

    experiment Kill the process between the charge call and the insert in a test; check whether the provider's confirmation callback alone is enough to recreate the order.

  4. ? What if it's out of stock?

    becomes When the last unit sells between the cart page and the Pay click, is the check made before the charge, after it, or both — and what happens to a charge for an unavailable item?

    experiment Two carts holding the last unit; complete both checkouts and observe which check ran and when.

None of these is a blocker. Each is a requirement that did not exist an hour ago, sorted into V1, deferred, or ask-the-stakeholder.

The same requirement, asked three ways

Discovery lives or dies on the quality of the question. "What about failures?" is a mood; it cannot be answered and so it is answered with "we'll handle it". The ladder below shows one discovered requirement climbing from a mood to something a stakeholder can decide and a test can check.

The best form names the actor, the moment, and the observable outcome. That is the shape of a requirement, and it is also the shape of a test — which is not a coincidence (Invariants as Tests).

From "handle failures" to a requirement
vagueWhat happens if something goes wrong during checkout?
betterWhat should happen when the payment provider declines the card?
bestWhen the provider declines the card after the customer clicks Pay, should an order exist afterwards, what does the customer see, and can they retry with the same cart?

why The best form makes three decisions visible — order state, customer experience, retry — that the vague form hides inside "goes wrong". A stakeholder can answer each in a sentence, and each answer is a test: no order row, a specific message, the cart intact.

Requirements as a tree, not a list

Once discovered, the requirements group by what the customer is doing rather than by layer, and every leaf carries the observation that would show it is met. A leaf you cannot describe an observation for is not yet a requirement; it is a heading with feelings under it.

The tree is deliberately not complete. It contains what was found and sorted into V1; the deferred items and the stakeholder questions live on the canvas, where they are visible without being built.

Checkout requirements, V1
Checkout
  • Before the chargethe cheapest place to fail
    • Stock is checked at Pay timetestable A cart whose item sold out after it was built fails at Pay with a reason, and no charge is attempted.
    • The total is recomputed from current pricestestable A price change after the cart was built is reflected in the charged amount and shown before Pay.
  • The chargethe external boundary and the money
    • A declined payment leaves no ordertestable After a test-mode decline, no order row exists, the cart is intact, and the customer sees the decline reason.
    • A repeated Pay creates no second chargetestable Two Pay requests for the same checkout id produce one charge and one order.
  • After the chargethe step where our own crash is the failure
    • A confirmed payment always ends in an ordertestable Killing the process after the charge and before the insert still produces exactly one order, via the provider's confirmation.
    • Confirmation shows the order that was createdtestable The confirmation page loads the order by id; a refresh shows the same order, not a new checkout.

Every leaf came from a "what if". None of them is in the ticket, and all of them are in V1.

How to do it

Most important first.

  • Write the happy path as numbered steps in plain English — no fewer than five, no technology. "Customer clicks Pay. We ask the provider to charge. Provider answers. We create the order. We reduce stock. We show a confirmation."
  • At each step ask: fails? repeats? state changed? crash here? Write every answer you do not have as a question (Failure-First Questions, What If Payment Fails?).
  • Turn each question into a requirement with an observable outcome: "a second click on Pay does not create a second order" rather than "prevent duplicates" (Functional Requirements).
  • Sort into V1, deferred-with-reason, and ask-the-stakeholder. Take the third column to the person who wrote the ticket before building anything that depends on it (Asking People).
  • Put the whole thing on the requirement canvas — goal, actors, actions, data, external systems, failures, unknowns, first milestone — so the next person can see what you decided and why.

Worked on a concrete problem

The move has to produce something. This is what it produced.

  • The happy path: cart → click Pay → charge via provider → create order → decrement stock → confirmation. Six steps, written in five minutes. Then the questions. Step "charge via provider": what if it fails — declined, timeout, provider down? What if it repeats — the customer clicked twice, or the browser retried? Step "create order": what if we crash after the charge succeeded but before the order row is written? Step "decrement stock": what if the last unit sold between the cart page and the click?
  • Discovered requirements, as sentences with outcomes: "A declined payment leaves no order and tells the customer why." "A second Pay click within the same checkout creates no second charge and no second order." "If the provider confirms a payment for which we hold no order, the payment is recorded and reconciled — nobody is charged for nothing." "If an item is out of stock at Pay time, checkout fails before the charge, not after." "A refresh during payment shows the current state of this checkout, not a blank cart."
  • Sorted: V1 — no double charge, no double order, out-of-stock before charge, declined payment explained. Deferred with reason — partial refunds (no returns flow in V1), saved cards (no accounts in V1). Ask the stakeholder — what does the customer see during a slow provider: a spinner for how long, then what? Can an order exist unpaid, and for how long?
  • Stopping point: the first slice is "create an unpaid order from a cart, with stock checked". None of the open stakeholder questions changes how that slice is built, so discovery stops and building starts. The questions stay on the board.

How you know it worked

What now exists that did not before, and what question you can now ask.

  • The requirement list is longer than the ticket and every extra line came from a specific "what if" you can point to.
  • Each requirement has an outcome someone could observe — a test, a log line, a screen — rather than a verb like "handle".
  • Three columns exist: V1, deferred with a reason, and questions for the stakeholder — and the third one has been sent.
  • You can name the first slice and say why no open question would change it.

The questions you can now ask

The field this whole domain exists for. After this lesson, these are the questions to put to an unfamiliar problem.

Next questions
  • ?What is the happy path, step by step, in plain English — and at which step does an external system or the user get a chance to surprise me?
  • ?At this step: what if it fails, what if it repeats, what if the state changed, what if we crash right here?
  • ?Which of the requirements I just found are V1, which are deferred with a reason, and which are not mine to decide?
  • ?Would building the first slice change if any open question were answered differently — and if not, why am I still asking?

What can go wrong

How the move itself fails
  • Discovery never ends. Every "what if" spawns three more, the list reaches sixty lines, and the first slice is still unbuilt. The stopping rule is "would the next step change?" — not "is the list complete?".
  • Every discovered requirement goes into V1. The move produces a list to sort, not a scope to accept; a team that cannot say "deferred, because" has turned discovery into scope creep.
  • The "what ifs" are asked of the wrong steps — the product page gets twelve failure questions and the payment step gets none — because the author asked where they were comfortable. Ask hardest where the external system and the money are.
  • The questions are answered by guessing. "What does the customer see during a slow provider?" is a product decision, and an engineer who invents the answer has built a requirement nobody asked for.
What the move costs
  • An afternoon of "what if" produces a list and no code; on a checkout you have built three times before, most of the list was already in your head.
  • A longer requirement list is harder to defend to a stakeholder who wanted "just checkout" — the argument about scope moves earlier, which is the point, but it is still an argument.
  • Discovered requirements are commitments. Once "no double charge" is written down, shipping without it is a decision rather than an oversight — which is more honest and less comfortable.
Misreads
  • "So I need a complete specification before I start." No — you need enough that the first slice is not a guess. The list will grow while you build; Requirements Emerge During Implementation is about the part you cannot find in advance.
  • "Discovery is the analyst's job." The person who writes the code is the one who finds "what if we crash between the charge and the order row", because they are the one who can see that there are two steps there. Discovery is engineering.
  • "Asking what-if is the same as building for failure." Asking is cheap and finds requirements; building each one is a separate decision. The Happy Path First lesson is about the order in which you build, not the order in which you ask.

Where this applies

Problem-solving advice is stated as universal far more often than it is. These labels say what each method is specific to — and where CONTESTED appears, the note gives the strongest form of the opposing view.

  • GENERALThe four questions — fails, repeats, state changed, crash here — apply to any workflow that touches an external system or persistent state; for a pure function they collapse to "what inputs are invalid?", which is the same move at a smaller scale.
  • STAGE-SPECIFICOn a greenfield checkout the "what ifs" are asked of a sentence; on an existing checkout they are asked of the running system, and half the answers are already in the code, the logs and the support tickets — read those before asking anyone.
  • ILLUSTRATIVEThe ticket, the six-step happy path and the discovered requirements are invented to show the move; a real checkout has more steps and its own list.

Where the depth lives

This domain asks the question and hands the answer off by name.

Further
  • The manifesto's review page at /manifesto/review asks what an LLM-generated checkout would have skipped — the "what ifs" here are the list it would have skipped.