You are stuck because X → do Y
The searchable index of this domain. The left column is how being stuck sounds — in your head, in a standup, in a ticket; the right column is the move, and the question it lets you ask next. Never a tool.
185 of 185 rows
How to Start7
| You are stuck because | Think |
|---|---|
| I have been told to build a store and I have eleven browser tabs open and nothing written down | You are before the Understand step, not short of ability. Write one paragraph saying what the thing is in the words of whoever asked, then the actors, their actions, and the one workflow whose completion means it works. The technology question only has content after that.I Have No Idea Where to Begin → |
| I keep switching frameworks | Every switch is a decision made about the tool while the problem stays untouched. Stop and write what the framework has to do for this problem — render a page, serve an endpoint, persist a row — and notice that almost anything you already know does it. Choose once the constraints give you a reason to prefer one.Technology-First Thinking → |
| The repo exists, the dev server runs, and I still do not know what to build next | The artefacts are about the framework, not the store. Go back to the loop: which requirement is next, which unknown blocks it, which slice would answer it. The next thing to build is chosen by the problem, not by what the scaffold makes easy.Problem Before Technology → |
| I do not know what the next step is | Ask what the next question is instead. Every stage of the loop has one: what is it, who uses it, what must be true, what do I not know, what is the smallest slice. If none of them applies, you are further along than you think and can start building.The Next Question → |
| I have a plan from an assistant and I cannot say why any step is in it | You have delegated the understanding, and the plan will break at the first step that assumed something about your problem. Rewrite each step in your own words with the reason it is there; the ones you cannot explain are the ones to investigate first.Understanding Is Not Delegable → |
| Everyone on the team is busy and nobody can say what done looks like | Motion is being mistaken for progress. Write the one workflow that has to work end to end and check whether any current task is on it. The tasks that are not are either preparation for it or a distraction from it, and you should be able to say which.The Problem-Solving Loop → |
| I am not sure this is even the right thing to build | Ask what the request is trying to achieve, in the requester's words, and what would be different for them if it existed. "A dashboard" is an implementation; "knowing by Monday which products are losing money" is a goal, and it might not need a dashboard at all.What Am I Actually Trying to Achieve? → |
Problem Framing5
| You are stuck because | Think |
|---|---|
| The request says "make search better" and I cannot start from that | Turn the vague goal into an explicit problem: better for whom, on which queries, measured how, compared with what. Each answer is a conversation with the requester or a look at the logs, and when they are answered "better" has become a problem you can decompose.From a Vague Goal to an Explicit Problem → |
| The ticket says "add a Redis cache to the product page" and I am not sure what problem it solves | An implementation has been handed to you as if it were a goal. Ask what the requester observed — a slow page? a database at capacity? — and write that down as the goal. Redis becomes one candidate among several, and may not be the one.Goal vs Implementation → |
| I explained the problem back and the stakeholder said "no, that is not it" | That is the move working. Restating exposes the gap between what was said and what was meant; keep restating until the correction stops. Each correction is a requirement you would otherwise have found in week three.Restating the Problem → |
| I have a list of thirty things the product might need and no way to order them | Ask what must be true for the thing to work at all, and set the rest aside for now, written down with the reason. A store must let someone pay; it need not have recommendations. "Ignored for now" is a decision you can revisit, not a decision you never made.What Can I Ignore for Now? → |
| Every conversation about the feature ends up somewhere different | The problem has not been framed, so each person is solving their own version. Write the framing on one page — what is being asked, for whom, what must be true, what is out of scope — and make the next conversation about the page rather than about the feature.Problem Framing → |
Requirement Discovery7
| You are stuck because | Think |
|---|---|
| Nobody asked how many users or how fast, and I do not know whether to design for it | The non-functional requirements are missing, not absent. Ask the numbers — users, requests, data size, acceptable latency, what happens if it is down for an hour — and write the answers, or the honest "we do not know", next to the functional list. Designs that ignore them are fast to write and slow to fix.Non-Functional Requirements → |
| The feature was "done" and then someone asked what happens when the card is declined | A requirement surfaced during implementation, which is normal — the happy path makes the failure path visible. Add it, and go through the workflow once more asking, at each step, "and if this does not happen?". The list you produce is the next iteration.Requirements Emerge During Implementation → |
| I am designing the retry logic for a checkout that does not create an order yet | Failure path before happy path. Build the sequence that works when everything cooperates, then inject each failure against it. A retry you cannot test against a working path is a guess — and the case where failure-first is right (a system whose whole job is handling failure) is not this one.Happy Path First → |
| The happy path works and I am not sure what else the thing needs | Now the failure path. Walk the workflow asking what if payment fails, the request repeats, the provider times out, the browser closes mid-way. Each answer is a requirement the happy path could not have shown you.Failure Path Second → |
| I have a requirements list and something about it feels incomplete | Look for the requirements nobody writes down: what admins do, what happens to existing data, what the system does on the first day with nothing in it, what is legally required. Ask the person who will operate it, not only the person who asked for it.Missing Requirements → |
| I have a list of features and cannot tell which are actually requirements | Write each one as an actor doing an action with an observable result: "customer adds a product to the cart and sees the count change". The ones that cannot be written that way are either non-functional, or wishes, or implementations in disguise.Functional Requirements → |
| I was given a one-line brief and told the rest is obvious | It is obvious to the person who has lived with the problem. Run requirement discovery anyway: actors, actions, data, boundaries, failures, and read the list back. The things that are obvious to them and were not on your list are the requirements.Requirement Discovery → |
Constraints5
| You are stuck because | Think |
|---|---|
| I do not know whether to build for the first hundred users or the first million | Ask the constraint, do not guess it. How many users in the first month, how much data, how much time to launch. The answer decides the architecture far more than any pattern does, and designing for a scale nobody has confirmed costs the time you needed for the workflow.Time, Users, Data → |
| The team knows PostgreSQL and the brief says the company standard is something else | Known technology and required technology are two separate constraints; write both down. The gap between them is a risk with a cost — learning time, mistakes — that belongs in the plan, not in a surprise in week four.Known vs Required Technology → |
| We built it and then legal said we cannot store that data there | Budget and legal are constraints that shape architecture, and they are the ones nobody tells the engineer. Ask early what data is regulated, where it may live, and what the running cost may be. The answer is a boundary, and boundaries are cheaper to draw before the code exists.Budget and Legal Constraints → |
| I drew an architecture and then discovered it has to run on one small server | Constraints shape architecture; the diagram came first and the constraint second, so the diagram is fiction. List time, users, data, known technology, budget and legal before drawing, and draw the smallest thing that satisfies them.Constraints Shape Architecture → |
| I have no idea what the constraints on this project even are | Ask six questions: how long, for how many, over how much data, with which technology you know or must use, for how much money, under which rules. Every "we do not know" is an unknown for the board, not a licence to assume.Constraints → |
Invariants5
| You are stuck because | Think |
|---|---|
| The store works until two people buy the last unit | An invariant — stock never goes below zero — was never written down, so nothing enforces it under concurrency. Name the properties that must always hold, then ask where each is enforced: in the request handler it is a race; in the database as a constraint or a conditional update it is a guarantee.Invariants Under Concurrency → |
| I do not know which rules are important enough to test | Find the invariants from examples: total is never negative, a payment happens at most once per order, a shipped order cannot be cancelled. Each one becomes a test that fails when it breaks, and the list is short enough to keep.Finding Invariants From Examples → |
| A refund made the order total negative and nobody noticed for a week | The invariant existed and was not a test. Write "order total is never negative" as an assertion that runs in the suite and at the boundary where the total changes; an invariant that lives only in a document is a hope.Invariants as Tests → |
| I cannot say what must never break in this system | Ask what would be a bug in every possible version of this product. Money that appears or disappears, a message delivered to the wrong room, a file readable by the wrong user. Those are the invariants, and the design has to protect them before it does anything else.What Must Never Break → |
| I am building a store and do not know which properties to protect first | Start with the ones money and stock depend on: an order is paid at most once, stock is never oversold, a captured price is the price the customer saw. Each one names a place in the design where a concurrency or a duplicate request would otherwise do damage.Invariants in an Online Store → |
Assumptions5
| You are stuck because | Think |
|---|---|
| We assumed one warehouse and now there are three and the design does not fit | The assumption was not written down, so nobody knew the architecture depended on it. Keep a register: each assumption, what depends on it, and what would change if it fell. When the requirement changes you know exactly why the design has to.When Assumptions Change → |
| I cannot tell which of my requirements are actually just things I assumed | A requirement came from someone who can confirm it; an assumption is something you decided in their absence. Mark each item with its source. The unmarked ones are assumptions, and each needs either a confirmation or a place on the register.Assumption vs Requirement → |
| The design is built on "users will always have an account" and I am not sure that is true | That is a dangerous assumption: it decides the cart's shape, the checkout, and the data model. Test it before building on it — ask the founder, look at competitors — because the cost of being wrong is the redesign, not a fix.Dangerous Assumptions → |
| Everyone in the room has a different picture of the system and nobody has said so | Make the assumptions explicit: write each one on the board — one currency, one language, orders never edited after payment — and let people disagree with the board. Unspoken assumptions are how two correct designs fail to fit together.Making Assumptions Explicit → |
| I want to record what we are taking for granted but do not know what form it should take | An assumption register: the assumption, who made it, what depends on it, how it would be checked, and when to revisit. It fits on a page and it is the document people actually read when the requirement changes.The Assumption Register → |
Unknowns7
| You are stuck because | Think |
|---|---|
| Every unknown feels like a blocker | An unknown is a question that has not been sharpened yet. "I don't understand payments" cannot be researched; "how does my backend find out a payment succeeded, and who is authoritative?" can be, in an afternoon with a test-mode account. Sharpen, run the tiny experiment, return to the main problem.An Unknown Is Not a Blocker → |
| I have a list of things I do not know and it is just making me anxious | Rewrite each item until it has a verb and an answerable form, then attach the smallest experiment that would answer it. The list becomes a research plan; anxiety is what an unsharpened list feels like.Unknown to Specific Question → |
| I have researched the unknown for two days and I am not closer | The question is still too broad to have an experiment. Cut it until a single afternoon's experiment would settle it — one endpoint, one table, one call to the provider — and run that. Reading widens the question; an experiment closes it.Unknown, Question, Experiment → |
| I do not know what I do not know | Unknown unknowns are found by walking the workflow and asking, at each step, what has to be true for this to work — and by talking to someone who has built one. Do not wait to discover them; go looking, and expect some to arrive anyway.Unknown Unknowns → |
| My question to the senior engineer got a shrug | The question was vague. "How do payments work?" has no answer; "which system should be authoritative for whether an order has been paid?" has one. Rewrite until the question names the decision you need made.Question Quality → |
| I cannot separate what I know from what I am guessing | Put it on a board: known, unknown, assumed, need to verify. Things move between columns as evidence arrives, and the board is what you show someone who asks how far along you are.The Unknowns Board → |
| I feel like I understand the problem but cannot say what I would need to check | Write what you know and what you do not in two columns. If the second column is empty, you have stopped looking, not finished. Every project has unknowns; the difference is whether they are on the page.Known and Unknown → |
Problem Decomposition8
| You are stuck because | Think |
|---|---|
| My decomposition is Frontend, Backend, Database and it does not help | That is true of every web application and says nothing about this one. Decompose by capability — catalog, cart, checkout, orders, payments — so that each piece can be built, tested and demonstrated on its own, and layers appear inside each piece where they are needed.Decomposition by Capability → |
| Checkout is one huge box on my diagram and I cannot start it | Decompose it again: validate the cart, compute the total, create the order, take payment, confirm. Each is small enough to write and test, and the sequence exposes the dependencies — the order must exist before the payment is attached to it.Decomposing Checkout → |
| I have forty subproblems and I am not sure any of them is right | A useful subproblem is testable — you can say what observation shows it works. Go through the forty and write that observation next to each; the ones without one are headings, and the ones with one are the plan.What Makes a Good Subproblem → |
| I broke the problem down and the pieces do not add up to the whole | Bad decomposition: pieces that are technical categories, that overlap, or that leave the core workflow uncovered. Trace the main workflow through the tree; if a step has no leaf, the tree is missing it, and if a step has two, they are entangled.Recognising a Bad Decomposition → |
| I do not know which piece depends on which | Draw the dependency map before choosing an order. Products must exist before a cart can hold them; an order must exist before a payment can reference it. The map is what tells you which piece cannot be built first no matter how valuable it is.The Dependency Map → |
| I decomposed once and the pieces are still too big to start | Decompose recursively: apply the same move to the biggest piece until each leaf is a few hours of work with a clear test. Stop when the leaf is smaller than the effort of describing it.Recursive Decomposition → |
| Someone says decompose by layer and someone else says by feature and they are both senior | They are answering different questions. By capability tells you what to build and demonstrate; by layer tells you where each capability's code lives. Use capability for the plan and layer for the structure, and notice that a plan made of layers cannot be demonstrated until the last one is done.Decomposition by Layer → |
| The whole problem is in my head at once and I cannot hold it | That is the signal to decompose. Write the root, then the three to six pieces a user of the system would recognise, then for each piece the observation that shows it works. The tree is the thing you can hold; the whole was never meant to be.Decomposing a Problem → |
First Principles5
| You are stuck because | Think |
|---|---|
| We have decided we need Kafka and I cannot say what for | Walk the why ladder. Why Kafka — for events. Why events — so the order service does not wait for email. Why not wait — the email provider is slow. The real requirement is "do not block checkout on email", and a job table with a worker meets it. Kafka is justified when several consumers need replay at a volume a table cannot serve — and only then.The Why Ladder → |
| The design has grown a queue, a cache and three services and the product is a todo list | Separate essential complexity — what the problem forces — from accidental complexity, which the solution added. A todo list's essential complexity is small; everything else is a cost with no bottleneck to justify it, and it should come out.Essential vs Accidental Complexity → |
| I cannot see the problem past the way we have always solved it | Remove the implementation assumptions one at a time: what if there were no queue, no cache, no service boundary? What remains is the fundamental requirement, and the options for meeting it are wider than the habit.Removing Implementation Assumptions → |
| I want to start with the right architecture and I am afraid the simple version will not scale | Build the simplest thing that could work and measure it. The simple version tells you where the real bottleneck is; the architecture that anticipates the bottleneck guesses, and a wrong guess costs more than a late right one. Where it flips: an irreversible decision — the data model, the tenancy boundary — deserves thought now.The Simplest Thing That Could Work → |
| Every discussion starts from a tool someone has used before | Go back to first principles: what does the problem require, independent of any product? Repeated reads of the same data are slow; that is the requirement. Then evaluate options against it, and the familiar tool competes on its merits.First Principles → |
Systems Thinking6
| You are stuck because | Think |
|---|---|
| We changed a price and the old orders changed with it | Change propagated through a shared reference. The order needed a snapshot of the price at the time of purchase, not a pointer to the product. Ask, for each piece of state, who reads it later and whether they want then or now.Change Propagation → |
| Three tables disagree about whether the order is paid | Nobody named the source of truth. Decide which system is authoritative for "paid" — usually the payment record confirmed by the provider — and derive the rest from it. Two authorities is one too many.Source of Truth → |
| The cart lives in the browser, the session and the database and they drift | Ask who owns this state. One owner, and the others are caches of it with a defined staleness. Until an owner is named, every fix moves the drift somewhere else.Who Owns This State? → |
| The payment provider was down and our whole checkout was down with it | External systems fail, and you did not decide in advance what your system does when they do. For each dependency outside your boundary, write what happens on timeout, error and silence — and whether the user is told, the work is queued, or the request fails cleanly.External Systems Fail → |
| I cannot tell what is ours and what is someone else's in this design | Draw the boundary. Inside is what you control and must make correct; outside is what you integrate with and must assume can fail. The email sender, the provider, the object store are outside — and every arrow across the line is a place for a contract and a failure mode.Inside and Outside the System → |
| Fixing one thing keeps breaking something else | The components are connected and the connections are not drawn. Map what reads and writes each piece of state, and trace a change through the map before making it. Systems thinking is the habit of asking "and then what happens?" one hop further than the fix.Systems Thinking → |
Abstraction Levels5
| You are stuck because | Think |
|---|---|
| "Checkout is slow" and I have opened the database query planner | You have zoomed to the bottom before looking at the top. Start at the highest level that could explain it — is it one request or many, the network, the application, the query — and go one layer deeper only when the layer above does not explain the observation.Highest Useful Level First → |
| I understand the framework's API and nothing underneath it | The framework is syntax over a mechanism — a request lifecycle, a state store, a query. Go one layer deeper on purpose, once: what does the framework do when this line runs? That is the knowledge that survives a framework change.Going One Layer Deeper → |
| I am debugging at the level of bytes and I have lost the plot | Zoom out. Restate the problem at the level of the user — what did they do and what did they see — then at the level of the system, then the component, and decide which level the evidence points at. Zooming is a deliberate movement in both directions.Zoom In, Zoom Out → |
| Every explanation of my system is either too abstract to be useful or too detailed to follow | Name the abstraction levels explicitly — user, workflow, service, module, function, query, storage — and say which level a given statement lives at. Mixing levels in one sentence is what makes explanations feel wrong.Abstraction Levels → |
| I know how to do this in one framework and not in any other | Ask what the framework did for you — routing, validation, persistence — and what the mechanism underneath is. Knowing the mechanism makes the next framework a syntax lookup; knowing only the framework makes it a new career.Framework Independence → |
Vertical Slices5
| You are stuck because | Think |
|---|---|
| I spent a week on the database schema and have nothing to show | Horizontal layers: each complete in itself, none demonstrable. Build a vertical slice — one product, one endpoint, one page — and show it. The schema will change once the first slice tells you what the product actually reads.The Horizontal Layers Trap → |
| The pieces are all written and they do not connect | Build a walking skeleton first: the thinnest path through every layer, doing almost nothing, deployed. It proves the environment and the seams before there is anything in them. Then grow it.The Walking Skeleton → |
| My "slice" has a frontend, an API and a database and I still cannot say whether it works | A slice is testable or it is a demo. Write the observation before building it: "a product created in the admin appears on the product page with the same price". If no such sentence exists, the slice is too wide or has no output.A Slice Is Testable → |
| I cannot find anything small enough to build first | Find the smallest executable thing: a single row returned by a single endpoint rendered by a single page. It is embarrassingly small on purpose, and it is the first thing that can be run, watched and grown.The Smallest Executable Thing → |
| The plan is database this week, backend next week, UI the week after | Replace it with slices: product page end to end, then cart end to end, then checkout. Each week ends with something a customer could do, and each slice tells the next one what it needs — which the layered plan finds out on the last day.Vertical Slices → |
MVP Thinking5
| You are stuck because | Think |
|---|---|
| The MVP list is the whole product with fewer colours | An MVP is the smallest version that proves the core idea, not the product minus polish. For a store: products, cart, order, payment. Everything else is "later, and here is why" — written down, because silently dropped scope comes back as a surprise.MVP Thinking → |
| Someone said "it's an MVP" to justify skipping the payment failure case | That is a bad prototype, not an MVP. An MVP simplifies what can be simplified — one currency, one warehouse — and never ignores what cannot be: money, correctness, the data you will need to migrate. The line is "would the core idea be disproved if this broke?".MVP vs Bad Prototype → |
| I cannot decide what is allowed to be out of V1 | Ask, for each feature, whether the core workflow completes without it. Recommendations, coupons, reviews, multi-currency: yes. Payment, stock, an order record: no. The first list is not V1; the second is the definition of V1.What Is Not V1 → |
| We shipped the MVP and now nobody knows what to add next | Grow from the MVP on evidence: what did users do, what failed, what did support get asked. The next feature is the one the evidence points at, and the evidence exists precisely because the MVP was small enough to ship.Growing From the MVP → |
| I want to simplify but I am afraid of simplifying the wrong thing | Some things cannot be simplified: an invariant, a legal requirement, a data model you would have to migrate under load. Name those first. Everything else can be a stub, a single case, a manual step, and that is where the simplification budget goes.What Cannot Be Simplified → |
Data Discovery5
| You are stuck because | Think |
|---|---|
| I do not know what tables this thing needs | Read the requirements aloud and write down the nouns: customer, order, product, payment. Then the relationships in the verbs: a customer places an order containing products. The entities are in the sentence; the tables follow from the entities, not the other way round.Entities From Requirements → |
| The order shows today's price instead of the price the customer paid | Snapshot against reference. The order item needed to copy the price at purchase time, because it must not change when the product does. Ask, for each field, "do I want this as it was then, or as it is now?" — the answer is the data model.Snapshots vs References → |
| I cannot decide what needs to be in the database and what can stay in memory | Ask what must survive a restart, a crash, and a second server. Orders and payments must. A browsing session probably need not. An anonymous cart is a decision — and writing it down as one is the point.What Must Persist → |
| I have a schema and I cannot explain it in plain English | Reverse it: write the plain-English sentences the schema should support — "a customer can have several addresses; an order ships to one of them" — and check each against the tables. Where the sentence has no home, the model is missing something.Data Modelling From Plain English → |
| I started the data model from what the framework scaffolds | Start from data discovery instead: what exists, what changes, what must persist, what references what. The scaffold's User and Post say nothing about your store. The model comes from the requirements; the framework then stores it.Data Discovery → |
Interface Discovery5
| You are stuck because | Think |
|---|---|
| I do not know where the API boundaries should go | Find the boundaries first: which pieces must communicate, and which of them are outside your control. Each boundary is where an interface is needed; each interface then needs a contract, a failure mode and an owner. Boundaries you did not find become interfaces you did not design.Where Does My System End? → |
| The user waits five seconds because we call four services before answering | Ask which dependency has to answer before the user can be told anything. Payment must; email and analytics need not. Everything that need not answer first moves off the request path, and the user waits for one thing instead of four.Which Dependency Must Answer Before the User Can Be Told Anything? → |
| The external API changed and our code broke everywhere | An external system was treated as part of ours. Wrap it behind one interface you own, translate its shape into yours at that line, and assume it will change, time out and disagree with you. The wrapper is where those assumptions are enforced.Treating External Systems as What They Are → |
| I have boundaries drawn and I do not know what the interfaces across them need | For each boundary, write what crosses it in each direction, what the caller needs back before it can continue, and what happens on failure. That is the interface, and the contract is the written version of it.Interfaces Emerge From Boundaries → |
| Two components talk to each other in five different ways and I cannot follow it | Interface discovery was skipped. List the pairs of components that must communicate, and for each pair the one channel and the one shape they use. Five channels between two components is four boundaries nobody designed.Which Components Must Communicate? → |
State Modeling5
| You are stuck because | Think |
|---|---|
| An order got shipped and then cancelled and refunded and now stock is wrong | The order lifecycle was never written as a state machine, so an illegal transition happened. Draw the states — created, paid, shipped, delivered, cancelled, refunded — and the allowed transitions; the illegal ones become checks, and the stock adjustment attaches to a transition.The Order Lifecycle, Built → |
| I cannot list what changes over time in this system | Ask what a user would notice if the system were frozen: order status, cart contents, stock, payment status, unread counts. Each is state, each has an owner and a history, and each is a candidate for a state machine.Overwrite or Append? → |
| There are booleans everywhere — isPaid, isShipped, isCancelled — and some combinations make no sense | Those are illegal states you can represent. Replace the booleans with one status whose values are the legal states, and the impossible combinations stop being representable.States That Must Be Unrepresentable → |
| I keep finding new statuses that the code has to handle | Do state-machine discovery on purpose: list every event that can happen to the entity and, for each current state, what the event does. The table finds the missing states before production does.Finding the State Machine → |
| The bug only happens in some sequence of actions and I cannot describe which | State discovery: what state does the sequence pass through, and which transition is the one the code did not expect? Write the states down and the sequence becomes a path you can reproduce.What Information Changes Over Time? → |
Failure Modeling6
| You are stuck because | Think |
|---|---|
| The customer double-clicked Pay and was charged twice | A duplicate request reached the payment step with nothing to recognise it. Ask "what if this request repeats?" of every step that has a side effect, and answer with an idempotency key, a unique constraint or a state check — before the second charge, not after.Duplicate Requests → |
| The payment succeeded but our database write failed and now nobody knows the order is paid | Partial failure: two systems changed and one confirmation was lost. Decide who is authoritative, reconcile from it, and make the confirmation handler safe to run again. The question is not "how do we prevent this" but "how do we recover from it".Partial Failure → |
| I have no idea how the system behaves when the database is down | Inject the failure. Stop the database, click checkout, and watch. Failure injection replaces a guess with an observation, and the observation is usually worse and more specific than the guess.Failure Injection → |
| We never asked what happens when payment fails | Ask it now, and the questions after it: fails how — declined, timeout, provider down? What does the customer see, what happens to the order, the stock, the cart? Each answer is a requirement and a test.What If Payment Fails? → |
| I want to be systematic about failures instead of remembering them one at a time | Failure-first questions, asked of every step: what if this does not happen, happens twice, happens late, happens after the user left? The four questions cover most of what production will do to you.Failure-First Questions → |
| The system works in the demo and falls over on the first real day | The happy path was modelled and the failures were not. Failure modeling is the second pass — after the happy path works — that lists what can go wrong at each step and decides, for each, whether to prevent, detect, retry or accept it.Failure Modeling → |
Pseudocode4
| You are stuck because | Think |
|---|---|
| I open the editor and cannot write the first line | Write pseudocode first: inputs, outputs, the state read and written, the branches, the failures. Syntax is the last problem, and it is easier when the shape already exists on the page.Pseudocode Before Code → |
| The function is written and I cannot say what it does when the cart is empty | The branches were never listed. Inputs, outputs, state, branches, failures — write them for the function, and the empty cart appears as a branch before it appears as a bug.Inputs, Outputs, State, Branches → |
| My pseudocode is just code with the semicolons removed | Pseudocode is a thinking tool, not a coding step. It should say what happens and why, at the level of the problem — "reserve stock; if any item is short, reject with the reason" — and leave the how to the code.Pseudocode as a Thinking Tool → |
| The pseudocode was clear and the code got complicated | Something in the translation added complexity the pseudocode did not have — usually framework ceremony or an unplanned branch. Diff the two: each line of code should point at a line of pseudocode, and the lines that do not are either accidental or a missing requirement.From Pseudocode to Code → |
Example-Driven Thinking5
| You are stuck because | Think |
|---|---|
| The abstract problem is too hard to think about | Construct a concrete case. Three units in stock, Alice buys two, Bob buys two at the same moment. Now the problem has numbers and a sequence, and the answer — someone must be told no — is visible.Example-Driven Thinking → |
| I cannot think of edge cases | Take the working example and push each value to its edge: zero items, one item, the last unit, a negative quantity, a price of zero, the same product twice. Edge cases come from examples, not from imagination.Edge Cases From Examples → |
| I am sure this design is right and I cannot prove it | Look for the counterexample: the one input, sequence or timing that breaks it. A design you have tried to break and could not is worth more than one you are sure of.Counterexample Thinking → |
| I want to know whether the design holds before building any of it | Run a thought experiment: walk one request through every component by hand, then one failure, then two requests at once. Most design errors are visible on paper to someone who does this honestly.Thought Experiments → |
| Someone asked "what happens at ten times the traffic?" and I have no answer | Run the scale thought experiment: multiply each number, find which component is first to be embarrassed, and ask whether the design changes or only the size. The answer is a reason to measure, not a reason to build.Scale Thought Experiments → |
Experiments & Prototypes6
| You are stuck because | Think |
|---|---|
| The prototype has been going for three weeks | A prototype answers a question, and this one was never given one. Write the question it exists to answer and the evidence that would answer it; if the question was answered on day two, the rest was a product being built without the rest of the loop.A Prototype Answers a Question → |
| I am about to design for three weeks before writing anything | Shorten the feedback loop. The design will meet reality eventually; the sooner it does, the cheaper the correction. Build the skeleton, run the experiment, write the smallest slice — anything that returns evidence in days rather than weeks.Short Feedback Loops → |
| The prototype worked so we shipped it | A prototype is built to answer a question and a production system is built to survive. The prototype skipped failure cases, security, logging and data migration because it was allowed to. Either rebuild with those, or say out loud that they are missing and why that is acceptable.Prototype vs Production → |
| I do not know whether this library can do what we need | Run a spike: a time box, one question, a throwaway repository, an answer. Two hours to find out whether the provider supports partial refunds beats two weeks of building on the assumption that it does.Spikes → |
| We ran the experiment and everyone read the result differently | The prediction was not written before the execution. Say what you expect to see and what each outcome would mean before running anything. An experiment without a prediction is a demo with extra steps.Prediction Before Execution → |
| I ran a test and I am not sure what it proved | Design the experiment before running it: what varies, what is held constant, what is measured, what result would change your decision. If no result would change the decision, do not run the experiment.Experiment Design → |
Debugging8
| You are stuck because | Think |
|---|---|
| I have been changing random things for an hour and nothing helps | Stop. Write the symptom, one hypothesis, and the observation that would confirm or rule it out. Then make that one observation. Debugging is hypothesis and evidence; mutation without a hypothesis cannot even tell you when it has succeeded.Do Not Randomly Change Things → |
| The bug happens in production and I cannot make it happen here | Reproduction first. Until you can make it happen on demand, every fix is a guess you cannot verify. Collect the exact input, state and sequence from the failing case, and shrink them until the failure still happens.Reproduce It First → |
| The reproduction needs the whole system running | Cut it down. Remove one component at a time and check whether the failure survives; what is left when it stops surviving is the cause's neighbourhood. The minimal reproduction is usually a few lines, and it is the thing to attach to the bug report.The Minimal Reproduction → |
| The error could be anywhere in a thousand lines | Binary search. Find a point where the state is right and a point where it is wrong, check the middle, and halve. Ten checks cover a thousand lines; reading them all covers nothing.Binary Search Over the System → |
| I added twenty print statements and now I am more confused | Logs are evidence, and evidence answers a question. Remove the prints, write the question — "does the request reach the handler with the right order id?" — and add the one log line that answers it.Logs Are Evidence, Not Thinking → |
| There is a stack trace and I skipped straight to the code | Read the error message. It names the failing operation, the value it saw, the line it came from and often the cause. Most debugging sessions that take an hour would take a minute if the message had been read to the end.Reading the Error Message → |
| I fixed it and I cannot say why the fix works | Predict before you change: "if the cause is X, then changing Y will make the symptom stop and Z will still work". If the fix worked and the prediction did not, you fixed a symptom. Debugging is a loop of symptom, observation, hypothesis, experiment and evidence — and the loop is what this domain is for.Debugging Is Problem Solving → |
| I made a change to test a theory and I cannot remember what I expected to see | Write the prediction down before running anything, even one line. A debugging step without a prediction cannot be judged, and a run of unjudged steps is what an hour of confusion is made of.Predict Before You Look → |
Reading & Reverse Engineering Code5
| You are stuck because | Think |
|---|---|
| I have been dropped into a codebase of two thousand files | Do not try to read all of it. README, entry point, the main feature, the data model — then follow one request from the outside in. Understanding a codebase means being able to predict where a change goes, not having seen every file.Reading a Codebase → |
| The bug is in code I have never seen and nobody who wrote it is here | Debug unknown code the same way as known code, plus one step: find the boundary. Where does the input enter, where does the state live, where are the side effects. Then reproduce, hypothesise, observe — the code being unfamiliar changes the pace, not the method.Debugging Code You Did Not Write → |
| I cannot tell what this system does from its code | Follow the data. Pick one record — one order — and trace where it is created, every place it is read, every place it changes. The system's real behaviour is the path the data takes, whatever the folder names say.Follow the Data → |
| There is no documentation and I need to know how the system works | Reverse-engineer it: the external behaviour first (what goes in, what comes out), then the state (what persists), then the boundaries (what it calls), then the internals only where the change needs them. Write down what you find; you are producing the documentation.Reverse Engineering a System → |
| I copied the code from an answer and it works and I do not know why | Copying is fine; copying without understanding is a debt. Rewrite the copied piece in your own words, change one input and predict the output, and remove anything you cannot explain. Whatever survives is yours.Before You Copy Code → |
Reading Documentation5
| You are stuck because | Think |
|---|---|
| I watched three tutorials and cannot build anything without a fourth | Tutorial dependency. Close the tutorial, write what you were trying to build, and read the documentation for the concept you need — not the walkthrough that happens to use it. Then build the smallest thing and modify it until it is yours.Tutorial Dependency → |
| The documentation is four hundred pages and I need one answer | Goal, relevant concept, minimal section, try the example, modify it, apply. You are looking for one concept; find its page, run its example, change one thing, and stop. The rest of the manual is for another day's question.A Reading Strategy for an Unfamiliar Library → |
| I cannot find anything useful with search | Search is a skill: name the mechanism, not the symptom; add the exact error text in quotes; include the version. "checkout slow" finds nothing; "postgres sequential scan on indexed column" finds the explanation.Search as a Skill → |
| The tutorial's architecture looks nothing like what we run | Tutorials orient; they are not a picture of production. Its client-side cart made the video shorter; its skipped payment failure made the video watchable. Use the documentation for what the pieces do, and design the arrangement from your requirements.Documentation Before Tutorials → |
| I read the docs and still cannot use the thing | Reading is not the goal; a working example you have modified is. Run the smallest documented example, change one parameter, predict what changes, and check. Understanding arrives through the modification, not through the page.Reading Documentation With a Goal → |
Researching Unknown Technology6
| You are stuck because | Think |
|---|---|
| Someone said "just use Elasticsearch" and I do not know what it is | Do not read everything about it. Five questions: what problem does it solve, what does it guarantee, what is the simplest example, how does it fail, what are the alternatives. An hour of those beats a day of the manual.Researching an Unknown Technology → |
| I have compared five technologies and I am no closer to choosing | You compared features; compare against your requirement. Write the one problem you need solved, then ask of each option only whether it solves that, what it costs to run, and how it fails. Most of the five drop out on the first question.Evaluating a Technology → |
| The technology has a hundred features and I cannot tell which matter | Ask what problem it was built to solve. Everything a tool does follows from that one problem; if your problem is not that problem, the features are noise, and if it is, the feature list is now readable.What Problem Does It Solve? → |
| It worked in the demo and lost data in production | You knew what it did and not what it guaranteed. For every piece of infrastructure, find the guarantee — durability, ordering, delivery, consistency — and the failure modes in the documentation, before it holds anything you care about.Guarantees and Failure Modes → |
| The top search result says one thing and the second says the opposite | Evaluate the result: how old, which version, does it show evidence or assert, is the author solving your problem or selling something. A four-year-old blog post about a different major version is not a source; the changelog is.Evaluating What the Search Returned → |
| We are about to adopt a queue and nobody here has run one | Run the smallest experiment with the new technology: one producer, one consumer, one message, then kill the consumer mid-message and see what happens. An afternoon of that tells you more about the operating cost than the whole feature page.The Smallest Experiment With a New Technology → |
Asking Better Questions2
| You are stuck because | Think |
|---|---|
| I am afraid to ask because the question will sound stupid | A question that names what you know, what you tried and the specific thing you need decided does not sound stupid; it sounds like work. "I have the order created and the payment intent; which system should be authoritative for paid?" gets an answer in a minute.Asking People → |
| I have a hundred questions and the meeting is fifteen minutes | Ask the ones that reduce the most uncertainty: the ones whose answer changes what you build next. "Do customers need accounts?" reshapes the cart; "which shade of blue?" does not. Order by what the answer unblocks.Questions That Reduce Uncertainty → |
Trade-Off Analysis6
| You are stuck because | Think |
|---|---|
| Every option has a downside and I cannot choose | That is what a trade-off is. Lay the options across the dimensions that matter here — simplicity, performance, reliability, cost, security, time, maintainability — say which two dimensions decide this case, and choose on those. Not choosing is also a choice, and it costs time.Trade-Off Thinking → |
| We have spent three meetings on a decision we could undo in a day | Reversible decisions deserve a quick choice and a note; irreversible ones — the data model, the tenancy boundary, the public API — deserve the meetings. Sort the decision first, then spend deliberation in proportion.Reversible vs Irreversible Decisions → |
| The matrix says option B scores 37 and option A scores 35 | That is fake precision. The scores are opinions in rows; a two-point difference is noise. Use the matrix to see which dimensions matter and where the options actually differ, then decide with a sentence, not a sum.The Trade-Off Matrix, Without Fake Precision → |
| We cannot decide because we do not have enough information | You will never have enough. Decide with what you have, write down the assumption you are deciding on and the evidence that would make you revisit, and make the decision as reversible as you can. Waiting is deciding to have the same information later.Deciding Under Uncertainty → |
| Nobody remembers why we chose this database | A decision journal: what was decided, the alternatives, the evidence, the assumptions, and when to revisit. It is five lines per decision and it is the difference between "we chose it for a reason" and "we chose it".The Decision Journal → |
| People keep saying "it depends" and never on what | Name the dimensions it depends on. Simplicity, performance, reliability, cost, security, time, maintainability — and for this decision, which of them are at stake and which are not. "It depends" becomes "it depends on whether we can tolerate an hour of downtime".Trade-Off Dimensions → |
Estimation & Ordering4
| You are stuck because | Think |
|---|---|
| The estimate was two weeks and it's week five | The estimate was one number for an undecomposed problem, so it could not have been right. Decompose, give each piece a best, likely and worst, and aggregate; the result is a range, and the pieces you have never done before are the ones that widen it. Report the range.Estimation as Decomposition → |
| I said "probably three weeks" and it was heard as a promise | Communicate the uncertainty in the same sentence as the number: "two to five weeks; the payment integration is the part I cannot bound". A range with its reason survives contact with a calendar; a number does not.Communicating Uncertainty → |
| The easy parts are done and the hard part is left for the last week | The riskiest unknown went last. Order by risk: prototype the part nobody has done — the payment provider, the concurrent stock update — first, while there is time to change the design if it fails.Risk-First Development → |
| I have the pieces and cannot decide which to build first | Four questions: what does everything else depend on, what is riskiest, what is most valuable to the user, what would I learn most from. Dependencies gate the order; among the unblocked, risk and learning early, value soon after. The riskiest unblocked piece is the one to prototype now.What to Build First → |
Build vs Buy4
| You are stuck because | Think |
|---|---|
| We are three weeks into building our own payment processing | Ask whether payments are your differentiation. They are not; they are a solved problem with a regulatory burden. Buy, and spend the three weeks on the thing customers chose you for. Build when the capability is what makes you different, or when no provider fits the constraint.Core Differentiation → |
| The provider is cheap and the integration is taking a month | The licence is the smallest part of the cost. Count the integration, the operating cost, the monitoring, the upgrade path and the team's time — and compare that with building the small version. Sometimes the cheap provider is the expensive option.Integration and Operating Cost → |
| The provider had an outage and we had no plan | Ask "what happens when the provider fails?" before signing, and decide: fail the request, queue the work, fall back, or degrade. The plan is part of the buy decision, not something to invent during the outage.When the Provider Fails → |
| Someone always wants to build it and someone always wants to buy it | Replace the argument with the questions: is this core, can a provider solve it, what does integration cost, what does operating it cost, what happens when the provider fails. The answers decide it; the preferences do not.The Build-vs-Buy Questions → |
Iterative Development7
| You are stuck because | Think |
|---|---|
| The team wants to add a message queue and the site has forty users | Run the complexity ledger: which problem, which measured bottleneck, what does it cost to operate, what happens when it fails, what is the simpler thing. At forty users no reading justifies it; a table and a worker meet the need. The queue earns its place when the table cannot keep up — and you will see that in a graph.The Complexity Ledger → |
| I want the final architecture before writing the first line | Let the architecture emerge from the requirements and the readings. Start with one server and one database; add a component when a measured bottleneck names it. The architecture drawn in advance is a guess about load nobody has seen.Architecture From Requirements → |
| Should I build the foundations first or the thing users will see? | Dependency-first when the foundation is genuinely load-bearing and cheap; value-first when the user-visible slice tells you what the foundation needs. On most product work, value-first with a walking skeleton wins, because the slice corrects the foundation before it hardens.Value First → |
| I cannot build checkout because nothing it depends on exists | Then the dependencies come first — products, a cart, an order record — but each as the thinnest version checkout needs, not the finished thing. Dependency-first is about order, not about completeness.Dependency First → |
| We are adding a cache because caches are what real systems have | Add complexity only when a requirement or a measurement demands it. What is the read latency now, what is the target, and which reads repeat? Without those numbers the cache is a guess that costs invalidation bugs — and with them it may be an index instead.Add Complexity Only When Required → |
| We are on iteration seven and each one starts from scratch | Iterative development keeps what the last iteration learned. Each round should start from a working version and a list of what the previous one showed — the failures, the surprises, the measurements — not from a blank plan.Iterative Development → |
| I have an order of work and I am not sure it is the right one | There is more than one right order. Write yours with the reason for each step, then write a second valid order and when you would choose it. If you cannot write the second, you have a habit rather than a plan.Implementation Order → |
Learning Without AI6
| You are stuck because | Think |
|---|---|
| I cannot build anything without an assistant open | Make the first attempt alone: your understanding, your decomposition, your pseudocode, your code. Then use the assistant on the attempt, not instead of it. What you cannot start without help is what you have not learned.No AI on the First Attempt → |
| I understood the solution when I read it and cannot reproduce it now | Build it from memory. The place where you hesitate is the part you did not understand; go back to that one part, not the whole thing, and try again tomorrow.Build From Memory → |
| I think I understand this and I am not sure | Explain it back to someone, or to a page, without looking. The sentence that will not come is the gap. The Feynman check is cheaper than finding the gap in production.The Feynman Check → |
| I am stuck on a practice problem and the answer is one click away | Take one rung of the hint ladder: the conceptual direction first, then the relevant abstraction, then pseudocode, then a partial implementation. Stop at the rung that unsticks you. The reference is the last rung, not the first.The Hint Ladder → |
| I finished the course and cannot start a project | The course carried the decomposition for you. Learn without the scaffolding: pick a small project, write what it is and how it breaks down, and build it from your own outline. The first one will be slow, and that is the learning.Learning Without AI → |
| My explanation of my own design convinced nobody, including me | Explain it back in the listener's terms: what it does for the user, then what each piece is for. If a piece has no sentence in that explanation, it either has no purpose or you do not know it yet.Explain It Back → |
Using AI Without Losing Understanding7
| You are stuck because | Think |
|---|---|
| I asked the AI and pasted it and now I can't debug it | The answer was used before it was understood, so nothing in your head predicts what it does. Rewrite it in your own words, predict the output for one input, run it, and diff. Use the tool for the next question — "why does this branch exist?" — rather than for the next paste.Good Tool Use → |
| The assistant's review says my code is fine and I do not trust it | Give it something to review against: the invariants, the failure cases, the requirement. "Does this handle a duplicate request?" gets a useful answer; "is this good?" gets agreement. A reviewer is only as good as the question.AI as Reviewer → |
| I am pasting the error into the assistant and pasting the fix back | Use it as a debugging partner instead: state the symptom, your hypothesis and what you observed, and ask what evidence would distinguish the candidates. Then go and observe. The loop is still yours; the partner widens the hypothesis list.AI as Debugging Partner → |
| If the assistant went away tomorrow I am not sure what I could still build | That is the dependency check, and the honest answer is the syllabus. List what you would need to relearn and work through it without the tool, one thing at a time. The tool is allowed to accelerate understanding; it is not allowed to replace it.The AI Dependency Check → |
| Everything in this repository was generated and nobody can explain any of it | Nothing exists without the model, which means nothing is owned. Pick the core workflow, have a person rewrite it in their own words with reasons, and treat what they cannot explain as unknowns on the board.If You Are Nothing Without the LLM → |
| The tool writes most of the code now; what is my job? | The problem framing, the requirements, the invariants, the decision about what is authoritative, the verification, the trade-off, the responsibility. The tool produces text; you still own whether the text is the right answer to the right question.What You Still Own → |
| I cannot remember what I tried last week or why | Keep an engineering notebook: current goal, assumptions, unknowns, decisions with evidence, experiments with predictions, findings, next step. It takes five minutes a day and it is the thing that makes the loop visible.The Engineering Notebook → |
Problem Solving Across Domains7
| You are stuck because | Think |
|---|---|
| I have a search over a sorted list and do not know which algorithm to use | Ask the constraint first: how big, how often, sorted or not, memory bound or time bound. Constraints lead to a pattern; the pattern leads to the DSA lesson. This domain hands off at the question.Problem Solving and DSA → |
| I found the entities and do not know how to turn them into a schema | You have done the discovery; the database domain owns the engineering. Take the entities, the relationships and the "must persist" list there, and the question you arrive with is "which of these needs a transaction?".Problem Solving and Databases → |
| I know what the endpoint has to do and not how a backend should do it | Arrive at the backend domain with the interface, the invariant it protects and the failure cases; it teaches the request lifecycle, idempotency and background work. The question you bring is "what must happen before I respond?".Problem Solving and Backend → |
| The workflow is clear and the UI state is a mess | The frontend domain owns rendering and state; arrive with the states the user can be in and the transitions between them. The question you bring is "which of this state is the server's and which is the screen's?".Problem Solving and Frontend → |
| I want to draw the system architecture and I have no load numbers | Then it is too early for system design as a discipline. Arrive at that domain with a measured bottleneck and the constraints; the question you bring is "which component is the first to fail at this load?".Problem Solving and System Design → |
| Someone said this needs machine learning and I do not know if it does | Ask what decision the prediction feeds and whether a rule already makes it. Business problem, target, data, metric — that is the handoff to the ML domain, and the first lesson there says when not to use it.Problem Solving and ML → |
| We want an agent for this and I cannot say why a workflow would not do | That is the question to bring to the agentic domain: why is one deterministic workflow insufficient? If the steps are known in advance, it is a workflow. An agent is justified when the next step depends on what the last one found.Problem Solving and Agentic Systems → |
Case Studies7
| You are stuck because | Think |
|---|---|
| I want to see the whole loop run on one problem from start to finish | The online store case: one sentence, framed, decomposed, sliced, failed on purpose and grown only as far as the evidence justified. Read it for the questions asked at each stage, not for the architecture at the end.Case: Build an Online Store → |
| I have to build a chat app and the store example does not fit | Same loop, different pivot. The chat app's core question is ordering and delivery: what does "received" mean, what if the same message is sent twice, what if the recipient is offline. Start from those, not from a websocket library.Case: A Chat App → |
| A URL shortener seems too small to need any of this | It is small enough to see the whole loop in an hour, which is the point. The requirement that shapes it is the read-heavy hot path; the invariant is that a code maps to one URL forever. Everything else follows from those two.Case: A URL Shortener → |
| File upload feels simple until I think about large files | The requirement that changes the design is the size of the body: where the bytes go, who owns them, what happens when the upload stops half-way. Ask those before choosing a storage service.Case: A File Upload Service → |
| "Add search" and I do not know whether it needs a search engine | Ask what is being searched, by how many, how fresh, and what "relevant" means for this catalog. A filter on a database column serves the first version of most product searches; the engine comes when the readings say the column cannot.Case: Search Products by Name → |
| The analytics dashboard is slow and everyone wants a data warehouse | Ask which queries, over how much data, how fresh, for how many viewers. Most dashboard problems are a missing aggregate table refreshed on a schedule; the warehouse is the answer when the questions are ad hoc over data the operational database cannot hold.Case: An Analytics Dashboard → |
| We want an AI assistant over our docs and the plan starts with a multi-agent framework | Start with the question the assistant must answer, the documents it needs, and the failure that matters most — a confident wrong answer. A retrieval step and one model call is the first version; add agents when a measured failure says the single workflow is insufficient.Case: An AI Assistant for Company Documentation → |