Learn Problem Solving & Engineering Thinking

How to move from a sentence you do not know how to build to the next question you need to answer. Thirty-three modules, from the first hour with a vague goal to using AI without losing understanding.

ProblemUnderstandRequirementsConstraintsUnknownsDecompositionSmallest StepModelExperimentObserveDebugLearnIterate

How to Start

7 lessons

"I have no idea where to begin." The loop that turns that sentence into a next question, and the technology-first reflex it replaces.

I Have No Idea Where to Begin
▶ lab

"Build an e-commerce store" is not a task, it is a sentence. Before any technology, ask what it means: who uses it, what they do, what data exists, what must persist, what can wait — until the smallest useful version is visible and the next question is obvious.

Q · Someone hands you "build an e-commerce store" and you have never built one. What do you do in the first hour, and how do you know it was the right hour?
What Am I Actually Trying to Achieve?

Before "how", answer "what for": what will be different when this is done, for whom, and how would we tell? A goal you can check is the difference between building the store and building a store.

Q · You have been asked to build something and you can describe it, but not what it is for. How do you find the goal behind the request, and how do you know you have found it?
The Problem-Solving Loop
▶ lab

Problem → Understand → Requirements → Constraints → Unknowns → Decomposition → Smallest Useful Step → Model → Experiment / Implement → Observe → Debug → Learn → Iterate. Not a template — a map that says where you are and what comes next.

Q · You are somewhere in the middle of a problem and cannot tell whether you are making progress or just moving. What is the loop, where are you in it, and what does it say to do next?
Technology-First Thinking

"I want to build e-commerce" → React, Next, Postgres, Redis, Kafka, Docker, Kubernetes — a reflex, not a plan. Recognise it, understand why it feels like progress, and replace it with Problem → Requirements → Data → Workflows → Scale → Architecture → Technology.

Q · The first thing you did with the new problem was choose a stack, and it felt productive. How do you recognise the technology-first reflex in yourself, and what is the sequence that goes in its place?
Problem Before Technology
▶ lab

A technology is an answer. Before accepting one, find the question: what requirement it serves, what simpler thing meets it, what it costs to run, and what would have to be true for it to be the right call. The Why Ladder, applied to "we need Redis".

Q · A technology has been proposed — by you, a colleague, or the last article you read. How do you find the problem it is supposed to solve, decide whether that problem exists, and choose between it and the simpler thing?
The Next Question

The domain's promise in one move: from "I have no idea" to "I know the next question I need to answer". Progress on an unfamiliar problem is measured in questions sharpened, not features shipped.

Q · You do not know how to solve this and cannot see a path to knowing. What is the one thing you can always produce from that state, and how do you make sure it is the right thing?
Understanding Is Not Delegable

Documentation, search, AI, books, examples, libraries and frameworks all accelerate understanding, and the line is that none of them can replace it. The good tool-use loop, the Problem → Ask AI → Copy → Hope loop, and how to tell which one you are in.

Q · You have every tool — docs, search, an AI assistant, a framework that does most of it — and the problem is still yours. What do the tools do for you, what can they not do, and how do you use them without ending up unable to work without them?

Problem Framing

6 lessons

Turning a vague goal into an explicit problem: what is actually being asked, what must be true, what can be ignored for now, and goal against implementation.

Problem Framing
▶ lab

"Build an e-commerce platform" is a bad frame; "customers browse, add to cart, pay, and admins manage products" is better; adding what must never happen, what is outside the system and what V1 leaves out is better still. The frame is the first artefact.

Q · You have a sentence and you need a problem. What does a well-framed problem contain, what does a badly-framed one leave out, and how do you get from one to the other?
From a Vague Goal to an Explicit Problem
▶ lab

"I want to build something like Spotify" contains a problem, and a fixed sequence of questions extracts it: who, what they do, the one workflow that matters, the data, the boundaries, what can wait, what you do not know. The output is a first slice, not a design.

Q · A goal has arrived as an ambition — "something like X" — rather than as a problem. What sequence of questions turns it into a problem you could start on, and what does the output look like?
Goal vs Implementation

"The user can pay" is a goal. "Stripe Checkout" is an implementation. Requirements that arrive as implementations lock in decisions nobody made; the move is to separate the two so the goal can be met by the best implementation, not the first one named.

Q · A requirement has arrived already containing its solution. How do you separate the goal from the implementation it came wrapped in, and when is the implementation actually part of the requirement?
Restating the Problem

Say the problem back in your own words — to the requester, to a colleague, to the page — before solving it. The restatement is where misunderstandings surface, and it is the cheapest experiment in the domain.

Q · You think you understand the problem. How do you find out whether you do, before the cost of being wrong is a week of code?
What Must Be True?

For "checkout works" to be true, a set of smaller things must each be true: the cart total is right, stock exists, payment succeeded exactly once, an order was recorded. Decompose the frame into conditions, and each condition is a test and a place a design decision lives.

Q · The frame says what the system does. How do you turn "it works" into the list of things that must each hold, and what does that list give you that the frame did not?
What Can I Ignore for Now?

A frame lists everything the system will need; V1 needs a fraction of it. Deciding what to ignore — and writing down why, and what would bring it back — is how a project gets small enough to start without forgetting what it left out.

Q · The frame is complete and it is too big to build. How do you decide what to leave out of the first version, how do you tell "ignore for now" from "ignore at your peril", and how do you make sure the ignored things come back?

Requirement Discovery

7 lessons

Functional and non-functional requirements, the ones that only appear during implementation, and the order: happy path first, failure path second.

Requirement Discovery
▶ lab

"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.

Q · 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?
Functional Requirements

A functional requirement says what the system does, for whom, with what observable result. "Manage orders" is not one; "an admin can change an order from paid to shipped and the customer is notified" is. The test is whether you could watch it happen.

Q · How do you write down what the system must do in a form that can be built, tested and argued about — rather than a list of verbs that everyone agrees with and nobody can check?
Non-Functional Requirements

Latency, security, availability, accessibility, cost, auditability, scale — the qualities of a system, each of which is a requirement only when it has a measurement and someone who cares about it. The skill is finding the ones this system actually has, and refusing the ones it does not.

Q · Which qualities does this system genuinely need — measured how, for whom — and which ones are being added because they sound like what serious systems have?
Requirements Emerge During Implementation

Some requirements cannot be found by asking; they appear when the first slice runs and the code asks a question nobody had. That is not a failure of discovery — it is the other half of it — and the move is to notice the question, write it down as a requirement, and decide rather than improvise.

Q · When building the first version reveals a requirement nobody stated, how do you tell a real requirement from an implementation detail, and what do you do with it?
Happy Path First

Build the sequence where everything goes right — cart, pay, order, confirmation — before any failure handling, because the happy path is the thing the failures are failures *of*. The order is contested: the failure-first camp has a real argument, and this lesson says where each wins.

Q · Should the first working version of checkout handle payment failure, duplicate clicks and crashes — or should it work end to end with everything going right, and grow failure handling afterwards?
Failure Path Second

With the happy path working, each discovered failure becomes an injection: break the provider, click twice, kill the process, sell the last unit — against real code — and watch what happens before deciding what should. Failure handling designed from observation, not from imagination.

Q · The happy path works and the failure list is long. How do you turn "handle payment failure" into specific, tested behaviour — and how do you decide what each failure should do?
Missing Requirements
▶ lab

A brief is defined as much by what it leaves out as by what it says. "Build a payment service" that never mentions currencies, refunds, idempotency, a provider or a ledger is not a short brief — it is a brief with five decisions hidden in it, and the strong learner asks before building.

Q · You are given a short brief for something with money in it. How do you find what it does not say, and how do you decide which omissions to ask about and which to assume?

Constraints

5 lessons

Time, users, data, the technologies you know and the ones you must use, budget and legal — the questions whose answers shape the architecture before any diagram.

Constraints
▶ lab

Seven questions decide the design more than most requirements do: how much time, how many users, how much data, which technologies I know, which I must use, what budget, what law. Ask them before the diagram, because a design made without them is made for a project that does not exist.

Q · What do you need to know about the situation — not the problem — before any design decision is honest, and what happens to a design that skips those questions?
Time, Users, Data

The three quantities that shape a design most — how long you have, how many people will use it, how much data there is and how it grows — and the habit of answering them with a number and a source instead of with "a lot" or "not much".

Q · How much time, how many users, how much data — and how do you get honest answers to those three when everyone involved would rather give you an adjective?
Known vs Required Technology

Two technology constraints that look alike and are opposites: what the team already knows, and what the situation imposes. The first is a soft constraint that decides most choices by default; the second is a hard one that has to be understood rather than resented — and the "we must use X" that is neither is the one to challenge.

Q · When should the technology you know decide the design, when should the technology you are told to use, and how do you tell an imposed technology from a preference wearing its clothes?
Budget and Legal Constraints

The two constraints engineers most often leave to someone else and most often get surprised by. Budget decides how many pieces the system may run and how; law decides what may be stored, where, for how long and who may see it. Both are design inputs, and both are cheapest when found before the schema exists.

Q · What do the money and the law require of this system, who owns those answers, and how do you get them into the design before the design makes them expensive?
Constraints Shape Architecture

Given the same requirements, two different sets of constraints produce two different correct architectures. The store with six weeks, two developers and tens of users is a monolith on one server; the same store with a partner sending a launch spike and a platform team is something else. Neither is the "right" architecture — each is the right one for its constraints.

Q · How do the constraints turn into an architecture, and how do you know whether a design decision came from a constraint or from taste?

Invariants

5 lessons

Properties that must always remain true — an order total is never negative, a payment never happens twice — found from examples and turned into tests.

What Must Never Break

A feature list says what the store does. An invariant says what it must never do — an order total is never negative, a payment never happens twice — whatever feature, bug or concurrent user is involved. Finding them is a different question from finding requirements, and it is asked before the data model.

Q · You have a list of what the store should do. What is the separate list of things that must never be true, and how do you find it before the code decides it for you?
Finding Invariants From Examples

Abstract state is hard to reason about; a concrete case is not. Construct a small example — three units, two buyers, one price change — walk it step by step, and the property that must hold falls out of the moment the example goes wrong. Counterexamples find invariants faster than definitions do.

Q · You cannot see what the invariants of a system are by staring at its entities. How do you construct examples that make the invariants visible — and the ones that are not really invariants fall away?
Invariants in an Online Store
▶ lab

The running example, worked fully: an order total is never negative, every order item references a product, a payment never happens twice, inventory is never negative. For each — who can violate it, where it is held, and what happens when it is not. The invariants decide the schema and the transaction boundaries before either exists.

Q · For the store you are building, what are the properties that must hold across every feature, and how do they decide where state lives and what a transaction has to cover?
Invariants Under Concurrency

Product A has three units. Alice buys two; Bob buys two at the same moment. Every line of both checkouts is correct and the store has promised four units of three. The example reveals the concurrency problem that no single-user test can see, and the thinking move is to name it as a question before choosing a mechanism.

Q · An invariant holds for every action taken alone. How do you find out whether it survives two of them at once — and what do you decide once you know it does not?
Invariants as Tests

An invariant on a page protects nothing after the person who wrote it leaves. Turned into a test that asserts the property after every sequence of actions — including the interleaving that found it — it becomes the only form of the rule that survives refactors, new endpoints and new engineers.

Q · You have a list of invariants and a design that holds them. How do you turn each one into something that keeps holding it after you have stopped looking?

Assumptions

5 lessons

Making assumptions explicit — one warehouse in V1 — so that when the requirement changes you know why the architecture has to.

Making Assumptions Explicit

"Only one warehouse in V1" is a fine simplification and a terrible secret. Written down with what depends on it, it becomes the reason you can later say exactly why "multiple warehouses" changes the inventory model, the checkout and the shipping estimate — instead of discovering it one bug at a time.

Q · Every design rests on things nobody checked. How do you find the ones yours rests on, and write them so that when one changes you know what has to change with it?
Assumption vs Requirement

A requirement is something somebody asked for. An assumption is something the design takes as true that nobody asked for. They look identical in a spec — "orders are in one currency" could be either — and confusing them means either building for a future that was never promised or treating a promise as if it could change.

Q · A sentence in the spec says the store handles one currency. Is that a requirement someone will hold you to, or an assumption you made to ship — and how do you tell, and why does it matter?
When Assumptions Change

"Multiple warehouses" arrives. If "one warehouse" was written down with its dependents, you know why the inventory model, the checkout and the shipping estimate all have to change, in what order, and which slice proves the new shape before the rest is rebuilt. If it was not, you find out one bug at a time.

Q · A requirement arrives that contradicts an assumption the design was built on. How do you turn "this changes everything" into a list of what changes, an order, and a first slice that proves the new shape?
The Assumption Register
▶ lab

A running list of what the system takes as true, when it was decided, why, what depends on it and what would make it false — kept beside the unknowns and the decisions, reviewed when a requirement arrives, and retired rather than deleted. The unknowns board is where it lives.

Q · You have learned to notice assumptions. Where do they go so that the team finds them at the moment a requirement changes — and how is the list kept alive without becoming another document nobody reads?
Dangerous Assumptions

Some assumptions are silently load-bearing: one currency, one timezone, one warehouse, users have accounts, the provider is up, a request arrives once. Each is reasonable for V1, each is invisible in the code, and each turns a requirement change into a redesign. Knowing the list is how you notice yours.

Q · Which assumptions are the ones that hurt — the ones that every V1 makes, that no code names, and that a single ordinary requirement turns into a redesign — and how do you find out which of them your system is standing on?

Unknowns

7 lessons

An unknown is not a blocker. "I don't understand payments" becomes a specific question, a tiny experiment, and a return to the main problem.

Known and Unknown

Before the unknowns can be worked on they have to be separated from what you know and from what you are merely assuming. The board with four columns — known, unknown, assumed, need to verify — is the first hour of any problem you have never seen.

Q · You have a problem you half understand. How do you find out which half, so the next hour goes on the half you do not?
An Unknown Is Not a Blocker

"I don't understand payments" feels like a wall. It is a sentence with no question in it. The move is to ask "what exactly don't I understand?" until the wall becomes "how does a backend initiate and confirm a payment?" — a thing you can go and find out this afternoon.

Q · You are stuck on something you do not understand. How do you tell whether it is stopping you, or whether you have merely not asked it a question yet?
Unknown to Specific Question

The rewriting step itself: how a topic becomes a question your system could ask. Subject, verb, object, the step of the workflow it serves, and the observation that would count as an answer.

Q · You have written down what you do not know and it is a list of nouns. How do you turn each one into a question that can be answered?
Unknown, Question, Experiment
▶ lab

The full detour from §14: Unknown → Specific Question → Research → Tiny Experiment → Understanding → Return to the main problem. The experiment is the step people skip, and it is the only step that produces knowledge rather than familiarity.

Q · You have a specific question about something you have never done. What is the smallest thing you could build that would answer it — and how do you stop it becoming a project?
Question Quality
▶ lab

The same need asked three ways: "how do payments work?" cannot be answered; "how does a backend confirm a payment?" is answered by a diagram; "which system should be authoritative for whether an order has been paid?" is answered by a decision. The ladder is how you tell where a question stands.

Q · You have a question about something unfamiliar. How do you tell whether it is good enough to answer yet — and what would make it better?
Unknown Unknowns

The board lists what you know you do not know. The unknowns that hurt are the ones not on it — and there are moves that surface them: asking what the experts in this area worry about, walking the failure paths, reading a real system's incident history, and listening for the word "just".

Q · Your unknowns board is written. How do you find the unknowns that are not on it — the ones you do not know enough to ask about?
The Unknowns Board
▶ lab

The board as a working document: four columns — Known, Unknown, Assumed, Need to verify — kept for the life of the feature, with the rules for what moves between columns and when. The lab at /thinking/unknowns is this board with a question assessor attached.

Q · You have learned to sort, sharpen, experiment and hunt for missing unknowns. How do you keep all of that in one place that stays true as the feature is built?

Problem Decomposition

8 lessons

The deepest module. Breaking a store into catalog, cart, checkout, orders and payments — then checkout into its steps — and telling a good decomposition from a technical one.

Decomposing a Problem
▶ lab

"Build an e-commerce platform" cannot be built; "list products", "add to cart" and "create an order" can. Decomposition is the move from the one to the other — and the split is judged by whether each piece could be built and checked on its own.

Q · A problem is too big to hold in your head at once. How do you split it so that every piece is something you could actually build and check, without the split itself being a week of diagrams?
Decomposition by Capability

Browse a product, add it to a cart, check out: a capability is something an actor can do, end to end, that you could demonstrate. Splitting a problem along capabilities gives every piece a test in the user's words and a natural order of work.

Q · What is the unit a problem should be split into, so that finishing a unit means something to the person who asked for the system?
Decomposition by Layer

Frontend, backend, database is a true statement about the solution and an empty one about the problem: it fits every application, so it distinguishes none. It is still the right split in a few specific situations — when the product is already known and one layer is the problem.

Q · When someone splits the problem into frontend, backend and database, what have they actually decided — and when is that the right split after all?
What Makes a Good Subproblem
▶ lab

A useful subproblem is understandable, testable, meaningful and small enough to build without further splitting. Most bad decompositions fail exactly one of the four, and naming which one tells you how to fix it.

Q · You have split the problem. How do you tell whether a piece is a real subproblem or just a heading with a confident name?
Recognising a Bad Decomposition

Layer-only, too wide, too deep, a single child, vague names: the five shapes a decomposition takes when it has stopped being about the problem. Each is visible in the tree's outline before any code is written.

Q · A decomposition can look complete and be useless. What are the shapes that give a bad one away, and what does each one mean you skipped?
Recursive Decomposition

A child that is still too big is decomposed the same way its parent was. Checkout becomes Load Cart, Validate Items, Calculate Total, Create Payment, Create Order, Confirmation — and the recursion stops where a leaf could be built on Monday and checked on Friday.

Q · Once a piece of the problem is still too big to build, how do you split it again — and how do you know when to stop splitting?
The Dependency Map
▶ lab

Checkout depends on Cart, Inventory, Payment and Orders — but not all in the same way. Some must answer before the customer can be told anything; some can be told later. Drawing the edges, and marking which kind each is, turns a tree into an order of work and a design for what happens when a dependency is slow.

Q · Which pieces of the decomposition need which others — and among those, which must be finished before you can respond to the user at all?
Decomposing Checkout
▶ lab

The whole module applied to one capability: checkout from a sentence to testable leaves, with the layer it crosses, the decisions the split surfaces, the dependency it cannot control, and the tool it did not need.

Q · Can you take the hardest capability in the store from "turn a cart into a paid order" all the way down to leaves you could build and check — without the decomposition becoming a design document?

First Principles

5 lessons

Removing implementation assumptions to find the fundamental requirement. "We need Redis" → why? → repeated reads are slow. Now evaluate options.

First Principles
▶ lab

"We need Redis" names a solution. First-principles thinking asks what problem it solves — repeated reads are slow — and only then evaluates options, of which Redis is one. The move is not "avoid tools"; it is "find the requirement before you choose".

Q · A requirement arrives already containing its solution. How do you get back to the problem underneath it, so that the solution can be chosen rather than inherited?
The Why Ladder
▶ lab

"We need Kafka" → why? → async events → why? → checkout should not wait for the email. The real requirement is "send the email asynchronously", and a job table meets it. Kafka may be overkill — and the ladder also says when it is not.

Q · Someone says "we need Kafka". How many times do you ask why, what do you do with the answer at the bottom, and how do you know when the original claim was right?
Removing Implementation Assumptions

Requirements arrive with implementation baked in: "the cart is stored in the session", "orders are a table", "search hits the database". Strip each implementation word and see what the sentence still requires — often less, sometimes something different.

Q · A requirement seems to force a design. How do you tell which parts of it are the requirement and which are someone's implementation, quietly included?
Essential vs Accidental Complexity

Payments can fail: that is essential, and every checkout must handle it. Five frameworks for one checkout: that is accidental, and it was chosen. The distinction tells you which complexity to design for and which to remove — and it is not always as clear as the slogan suggests.

Q · The system is complicated. How do you tell which of the complexity is the problem's and which is yours — and what do you do differently about each?
The Simplest Thing That Could Work

"Could work" is the half of the slogan people drop. The simplest thing that could work meets the real requirement — failure handling included — with the fewest parts; the simplest thing that does not is a demo. The move is finding the first, and knowing what evidence would make it insufficient.

Q · You have the real requirement. What is the simplest thing that could actually meet it — and how do you keep "simplest" from sliding into "incomplete"?

Systems Thinking

6 lessons

Changes propagate through connected components. Change a price and it reaches cart, checkout, order history and refunds — so where should price be captured, and who owns it?

Systems Thinking

Change a product's price and the change reaches the cart, checkout, order history and refunds. Following one fact through every component that reads it reveals where the fact should be captured — and it is rarely where the reflex puts it.

Q · A product's price changes. Which parts of the store are affected, and how do you find them before a customer does?
Change Propagation

Every component that reads a fact is a component the change must reach. Counting the readers, and the hops between writer and reader, tells you what a change costs and where it will be wrong — before it is made.

Q · How far does a change travel through the system, and how do you estimate that before making it?
Source of Truth

The current price of a product and the price a customer paid are two different facts with two different owners. Naming the source of truth for each fact — and noticing when one fact is actually two — is how the same number stops appearing in two versions.

Q · For each fact the system shows, which single place is authoritative — and is "the price" one fact or two?
Who Owns This State?

For each piece of information in the system, one component should be allowed to change it and everyone else should ask. Assigning an owner to every fact — cart contents, stock, payment status, read state — is how a system stays consistent without a coordinator.

Q · For every piece of state the system holds, which component is allowed to change it, and what happens when two of them think they are?
Inside and Outside the System

The payment provider, the email sender, object storage and the shipping carrier are not part of the store. Drawing the boundary — what we control, what we merely call — is the first step of every design, because everything outside the line can fail without asking us.

Q · Where does our system end, and which of the things the store depends on are on the other side of that line?
External Systems Fail

Everything outside the line can fail, can be slow, can change and can rate-limit — and will, on a schedule you do not control. For each crossing, deciding what the store does in each of those four cases is design work, not error handling.

Q · For each external system the store calls, what happens when it fails, when it is slow, when it changes and when it says "too many requests" — and who decided that?

Abstraction Levels

5 lessons

From "user clicks Buy" to the SSD in seven levels. Solve at the highest useful level first; zoom in when necessary; know that the framework is syntax over the mechanism.

Abstraction Levels

"User clicks Buy" is also a POST, a service method, a SQL transaction, a set of database pages, a filesystem write and an SSD operation. Naming the levels a problem lives on — and which one you are standing on — is how you stop mixing questions from different levels into one confused one.

Q · When a customer clicks Buy, how many different things are happening — and which of them is the one your problem is about?
Highest Useful Level First

Solve the problem at the highest level where it can be stated and checked, and go deeper only when that level cannot explain what you see. Most problems are solved at the top; the ones that are not announce themselves by a promise that holds and a symptom that persists.

Q · At which level should you try to solve this problem first — and what tells you that level was not enough?
Zoom In, Zoom Out
▶ lab

At the architecture level the store is Frontend → Backend → Database. Zoom into Backend and it is Router → Service → Repository; zoom into Database and it is Planner → Index → Pages. Every box is a system at the next zoom, and choosing the zoom is choosing which questions are visible.

Q · At which zoom level does this question have an answer — and what does each box become when you zoom into it?
Going One Layer Deeper
▶ lab

"Checkout is slow" → Backend → the database query → the B-tree → pages → the OS cache → the SSD. Each layer is a domain of its own, and the move is knowing when a layer's explanation is complete and when the next one down is required — never skipping a layer, and never going one further than the evidence sends you.

Q · When does a problem require going one layer deeper — and how do you know you have gone deep enough?
Framework Independence

Not "how do I create an Express route" but "an HTTP request arrives, a router matches it, a handler runs, a response is written". Learn the mechanism at the level below the framework and the framework becomes syntax — learnable in an afternoon, swappable in a week.

Q · What is the framework doing for you — and could you describe the mechanism without naming the framework?

Vertical Slices

5 lessons

Product page through API through database to a visible product, instead of a week of database then a week of backend. A slice is independently testable; a skeleton proves the pieces connect.

Vertical Slices
▶ lab

Not the database in week one, the backend in week two and the frontend in week three — but one product, from page to API to database and back, visible on day one. A slice is one narrow feature through every layer, and it is the unit in which a system actually becomes real.

Q · What is the smallest unit of work that, when finished, means something works — and why is it a path through the layers rather than one layer?
The Horizontal Layers Trap

Building layer by layer feels safe because each layer is a real thing that gets finished. The trap is that a finished layer proves nothing about the product, and every question about the product is deferred to the last week, when they all arrive together.

Q · Why does building one layer at a time feel like progress, and what specifically does it hide until it is too late?
The Walking Skeleton
▶ lab

Browser → API → Database → Browser, doing almost nothing, working end to end, deployed. A walking skeleton is the thinnest possible slice built to prove the pieces connect — and it deliberately proves nothing else.

Q · Before any feature is built, what is the smallest thing that would prove every part of the system can talk to every other part?
The Smallest Executable Thing
▶ lab

Create Product → Store Product → Display Product: three steps that together are the smallest thing a store can do that is worth watching. Find it, build it, watch it run, then grow it — because every grown step is tested against something that already works.

Q · Among everything the system must eventually do, what is the smallest sequence you could execute today and learn something from — and how do you grow from there without losing the ability to run it?
A Slice Is Testable

Create Order through Frontend → API → Business Logic → Database → Response can be tested on its own, before any other slice exists. That is what makes a slice a unit of progress rather than a unit of work — and the test must say what it does not prove as clearly as what it does.

Q · What does it mean for a slice to be independently testable, what does a passing slice actually establish, and what does it leave unknown?

MVP Thinking

5 lessons

The smallest version that proves the core idea — products, cart, order, payment — and the line between what can be simplified and what cannot be ignored.

MVP Thinking
▶ lab

The smallest version that proves the core idea — for the store, products, cart, order, payment — and nothing that does not change whether the idea is proven. Not the product with features removed; the product with the proof left in.

Q · What is the smallest version of this that would tell me whether the core idea works, and how do I stop it growing into the whole product?
What Is Not V1
▶ lab

Deciding what stays out is the same decision as deciding what goes in, made honestly: each excluded feature gets a reason, a trigger for revisiting it, and the assumption it leaves behind in the code.

Q · How do I say "not yet" to a feature in a way that survives the meeting, and what does saying it commit me to?
MVP vs Bad Prototype

An MVP simplifies scope and keeps correctness where the idea lives; a bad prototype simplifies correctness and keeps scope. The first tests an idea; the second tests whether customers notice.

Q · My V1 is small — but is it small in the right places, or have I cut the parts that make the result mean anything?
What Cannot Be Simplified

Most of a system can be simplified in V1; a few things can only be done or not done — money, identity, and data that cannot be recreated. Knowing which is which is the whole skill of scoping an MVP.

Q · Of everything in this system, which parts can I make smaller without making them wrong — and which parts have no smaller version?
Growing From the MVP

V1 shipped and something was learned. The next version is not "V1 plus the phase-2 list"; it is the smallest change that acts on what was learned, with each simplification undone only when its trigger fires.

Q · V1 is in front of real users. How do I decide what the next version is, and how do I keep it from becoming the full feature list I refused to build the first time?

Data Discovery

5 lessons

From "customer places an order containing products" to Customer, Order, OrderItem, Product. Entities from plain English, what must persist, and snapshots against references.

Data Discovery

"Customer places an order containing products" is already a data model: Customer, Order, OrderItem, Product. Entities are the nouns, relationships are the verbs, and the hidden entity is the one the sentence needs but does not name.

Q · Before I design a database, how do I find out what data this system is actually about?
Entities From Requirements

A requirement is a source of entities only if it is read for them. The rule is a noun the system must remember; the traps are nouns that are really attributes, attributes that are really entities, and the entity you only find by asking "one or many?".

Q · Given a list of requirements, how do I decide which nouns deserve to be entities, which are attributes, and which are neither?
Data Modelling From Plain English
▶ lab

"Users can create projects and invite members" hides User, Project, Membership and Invitation — two of which are verbs. The move is to read requirements as data until a first schema falls out, then hand the schema to Database Engineering to make it correct.

Q · How do I get from a sentence a non-engineer wrote to a first schema I could actually create, without designing a database I do not yet understand?
What Must Persist

Not everything the system knows must survive a restart. Orders must; a cart may; a product's "in stock" badge is recomputed. Sorting data into must-persist, may-persist and recompute is what keeps the schema small and the losses acceptable.

Q · Of everything this system holds in memory at some moment, what must still be there after a restart, what may be lost, and what should be recomputed rather than stored?
Snapshots vs References

The price the customer paid lives on OrderItem, not on Product. Whenever a fact was true at a moment and the thing it refers to can change, the fact is a snapshot; a reference is right only when the current value is the one wanted.

Q · When one entity refers to another, should it hold a reference to the current thing or a copy of the thing as it was — and how do I tell which?

Interface Discovery

5 lessons

Which components must communicate, where the boundary of our system is, and which external dependency has to answer before the user can be told anything.

Which Components Must Communicate?

An interface exists wherever two parts must agree on something. Find them by asking, for every workflow step, who has the information and who needs it — the browser, the backend, the database, the payment provider — and you have the interfaces before any of them has a shape.

Q · You have a list of components and a workflow that crosses them. How do you find every place where two of them must agree — before you design a single endpoint?
Where Does My System End?

The boundary of the system is the line between what you can change and what you can only call. Finding it — payment provider, email, image storage, the customer's browser — tells you which interfaces are contracts with a stranger and which are conversations with yourself.

Q · Which parts of the store are inside your system, which are outside, and how does knowing the difference change what you build at each edge?
Interfaces Emerge From Boundaries

Once the boundary is drawn, each edge crossing it is a contract to write — in your terms, not the stranger's. The interface says what your system needs from the other side and what it promises back; the provider's SDK is an implementation of that, not a definition of it.

Q · You have found the boundary. What does the interface at each crossing actually contain, and whose vocabulary should it be written in?
Which Dependency Must Answer Before the User Can Be Told Anything?

Checkout depends on cart, inventory, payment and orders. Not all of them must answer before the customer sees a result; asking which ones must — and what you would tell the customer if the others are still working — is the decision that separates a synchronous call from an asynchronous one.

Q · When a request depends on several components, which of them must answer before you can respond to the user — and how does that answer decide what is synchronous and what is not?
Treating External Systems as What They Are

An external system can fail, be slow, change, rate-limit you, and repeat itself. None of those is a bug in it; they are properties of being outside. The interface you design around it either accounts for all five or discovers them one incident at a time.

Q · Everything outside the boundary can fail, stall, change, throttle you and send things twice. What does each of those do to the interface you design around it?

State Modeling

5 lessons

What changes over time — order status, cart contents, inventory, payment status — and the state machines that fall out of asking.

What Information Changes Over Time?

Entities say what exists; state says what about them changes. Order status, cart contents, stock levels and payment status all change, each on a different trigger, and each one is a place where the system must know "the current value" — which is where most bugs live.

Q · You have the entities. Which of their attributes change over time, who changes them, and why does the answer matter more than the schema?
Overwrite or Append?

For every piece of state there is a choice: keep the current value, keep the history, or both. Stock is a number that is overwritten and a history that is appended; the choice depends on who will ask "why?", and getting it wrong is cheap to fix early and expensive later.

Q · For a piece of state that changes, should the system keep only the current value, the sequence of changes, or both — and what question decides it?
Finding the State Machine

When a piece of state has a small set of named values, the values are half the model; the other half is which transitions are allowed and who causes them. Order CREATED → PAID → SHIPPED → DELIVERED, with CANCELLED and REFUNDED as exits, is discovered by asking "from here, what can happen?" until nothing new appears.

Q · A status has a handful of values. How do you find the transitions between them, the ones that must not exist, and who is allowed to cause each — without a workflow engine?
The Order Lifecycle, Built
▶ lab

PENDING → PAID → FULFILLED, with CANCELLED and REFUNDED added later. Which transitions are legal, who triggers each, and in what order to build them so that the store works before the machine is complete — the state module applied end to end on the capstone's order.

Q · You know how to discover a state machine. In what order do you build the order's lifecycle so that every step leaves a working store, and which transitions can wait?
States That Must Be Unrepresentable

Paid twice, shipped before paid, refunded with no payment: some combinations of state must not merely be rejected at runtime but be impossible to write down. Finding them is a discovery move — ask which combinations of fields would be a lie — and where to enforce each is a decision, not a doctrine.

Q · Which combinations of state in the store must never exist, how do you find them, and where — type, constraint, transition — should each one be made impossible?

Failure Modeling

6 lessons

After the happy path works: what if payment fails, the request repeats, the database is down, the browser closes. Failure injected on purpose.

Failure Modeling

The basic path works. Now ask, step by step, what happens if the payment fails, the database is down, the request repeats, or the user closes the browser — and turn each answer into a state the system can be in and a test that puts it there.

Q · Checkout works when everything goes right. How do you find out, systematically rather than by accident, what happens when something goes wrong?
What If Payment Fails?
▶ lab

"Payment failed" is not one event. The card can be declined, the provider can time out, the browser can close after the charge, the confirmation can arrive twice. The question that sorts them is: who says the payment succeeded, and how does my system find out?

Q · The frontend says "Payment failed". What actually happened, which system knows, and what should the order be marked as?
Duplicate Requests

A payment must not happen twice, and the double click, the browser retry, the webhook redelivery and your own retry loop all make the same request twice. Idempotency is the name for the answer; the lesson is discovering the question.

Q · The same checkout request arrives twice. What should happen, where is it decided, and how do you know it works?
Partial Failure

The payment succeeded and the backend crashed before the order was written. Two things that were supposed to be one thing happened separately, and the system is now in a state nobody designed. The move is to find every such gap and decide what fills it.

Q · Checkout does several things across several systems. What happens if it stops half-way, and how do you find the gaps before a customer does?
Failure Injection
▶ lab

Once the store works, make it fail on purpose: a payment that times out, a product that runs out during checkout, a checkout submitted twice, a database that is not there. Each injection turns a failure you reasoned about into one you observed.

Q · You have a failure model on paper. How do you find out whether the system actually does what the paper says?
Failure-First Questions

Five questions to ask of any design, at any boundary: what if it fails, what if it is slow, what if it repeats, what if it arrives out of order, what if it is unavailable. They are dull, they are the same every time, and that is why they work.

Q · You are looking at a design you have never seen — a chat app, an upload service, a dashboard. What do you ask to find its failure modes without knowing the domain?

Pseudocode

4 lessons

Inputs, outputs, state, branches and failures written down before any framework syntax — pseudocode as a thinking tool, not a coding step.

Pseudocode Before Code

"function checkout(cart): validate cart, calculate total, create payment, create order, return confirmation" — five lines that say what checkout does, written before any framework decides how. The lines are where the missing decisions become visible.

Q · You understand the problem and are about to write checkout. What do you write first, and why not the code?
Pseudocode as a Thinking Tool

Pseudocode is not a notation for code you have not typed yet. It is a device for finding inputs you forgot, state you did not know you needed, branches you had not considered and failures you had not decided — and it works because it is too small to hide any of them.

Q · What is pseudocode actually for, and how do you write it so that it finds something rather than restating what you already knew?
Inputs, Outputs, State, Branches

The four things every operation has and pseudocode must show — what comes in, what goes out, what is remembered, where the path splits — plus failures, which are branches with consequences. Checkout under all five, and the chat app for contrast.

Q · What must a piece of pseudocode contain before it can be said to describe an operation, and how do you check it does?
From Pseudocode to Code

The pseudocode had six endings on one screen. The code has a route, a validator, an ORM, an SDK and a catch block — and, if you are not careful, one ending. What survives the translation, what the framework adds, and how to keep the branches visible.

Q · You have good pseudocode. How do you turn it into code without losing the decisions it made?

Example-Driven Thinking

5 lessons

When the abstract problem is hard, construct a concrete case: three units, Alice buys two, Bob buys two at the same time. Edge cases, counterexamples and thought experiments.

Example-Driven Thinking

"Design the inventory system" cannot be reasoned about; "three units, Alice buys two, Bob buys two at the same moment — what should happen?" can. A concrete example turns a design task into a question with an answer, and the answer usually reveals the requirement the abstract sentence was hiding.

Q · The problem is stated abstractly and you cannot get a grip on it. How do you construct a concrete example that makes the real question visible?
Edge Cases From Examples

Once one example exists, the edge cases come from varying it along a short, repeatable list: zero, one, many, duplicate, invalid, concurrent. The list is not a template — it is where the requirements the happy path hid tend to live, and each one either has an obvious answer or is a decision.

Q · You have the happy path and one worked example. How do you systematically find the cases that will break it, without guessing at random?
Counterexample Thinking

When a claim sounds right — "this always works", "that can never happen" — try to construct one case where it does not. A counterexample found in five minutes on paper is worth more than a week of confidence, and failing to find one after honestly trying is evidence, not proof.

Q · Someone — possibly you — says "this always works" or "that can never happen". How do you test the claim before the system does it for you?
Thought Experiments

Run the system in your head at one user, a hundred, a million — not to build for a million, but to see which assumptions hold at each size and where the design would first bend. A thought experiment is the cheapest experiment there is; it finds the assumption, and a real experiment then checks it.

Q · How do you understand what a design assumes without building it — and without sliding into building for a scale you do not have?
Scale Thought Experiments
▶ lab

Take the store from one server and one database to a size where something breaks, and watch which component is actually the bottleneck at each level — then see that a cache fixes reads and not writes, a queue fixes checkout wait and nothing else, and at low traffic every added component is unjustified. The lab runs the numbers; the lesson is how to read them.

Q · You have imagined the system at scale and named the assumptions. How do you tell which one actually bends first, and which component — if any — would move it?

Experiments & Prototypes

6 lessons

A prototype answers a question. Spikes, experiment design, predicting before running, and the feedback loop that beats three weeks of design.

A Prototype Answers a Question

"Can the browser upload a five-gigabyte file straight to object storage without going through our server?" is a question. A prototype that does only that — and nothing around it — answers it in an afternoon. A prototype built to "see how the upload feature would work" answers nothing and takes a week.

Q · You are about to build a prototype. What question is it answering, and what is the smallest thing that answers it?
Prototype vs Production

A prototype is allowed to ignore polish, scaling, error handling and extensibility — that is what makes it fast. The condition is that it says, in writing, what it ignored and therefore what it does not prove. A prototype that does not say so becomes production by accident, and the omissions become bugs nobody chose.

Q · What is a prototype allowed to skip, what is it never allowed to skip, and how do you stop it quietly becoming the product?
Spikes

A spike is a time-boxed investigation whose only output is reduced uncertainty: a question, a box of hours, an answer, and then a decision to discard or integrate. The time-box is what distinguishes it from research that never ends, and the written answer is what distinguishes it from a branch someone will find later and wonder about.

Q · There is something you need to understand before you can design the next piece. How do you investigate it without the investigation becoming the project?
Experiment Design

Question, hypothesis, test, observation, conclusion — the same structure whether the experiment is a load test, a spike or a debugging probe. The hypothesis is written before the test so the result can disagree with you; the observation is recorded before the conclusion so the conclusion cannot rewrite it.

Q · You are about to try something to find out whether it is true. How do you set it up so that the result can actually change your mind?
Prediction Before Execution
▶ lab

Before you run the code, say what you expect to see. If the output matches, you understood the system; if it does not, you have just found the exact place your model of it is wrong — and that is information you can only get by having committed to a prediction first. It is the cheapest experiment in engineering and the most skipped.

Q · You are about to run something — a test, a query, a request, a debugging change. What do you expect to happen, and what will you learn if it does not?
Short Feedback Loops

Change, run, observe, fix — minutes per cycle — beats design for three weeks, build everything, and discover on the last day that one assumption was wrong. The reason is not that thinking is bad; it is that the cost of a wrong assumption grows with everything built on top of it, and a short loop finds it before anything is.

Q · How long is it between making a change and knowing whether it was right — and what does that number cost you?

Debugging

8 lessons

Symptom, observation, hypothesis, experiment, evidence — and the anti-pattern of changing random things. Reproduction, minimal reproduction, binary search, logs as evidence.

Debugging Is Problem Solving
▶ lab

A bug is an unknown with a symptom attached. Symptom → observation → hypothesis → experiment → evidence → updated hypothesis is the same loop the domain uses for everything else, and it turns "Payment failed" into a sequence of questions each of which can be answered.

Q · The checkout page says "Payment failed" and you have no idea why. How do you make progress without knowing where the bug is?
Do Not Randomly Change Things
▶ lab

Error → change some code → restart → change something else is the most common debugging method and the worst. Instead ask what changed, what evidence exists, and which layer owns the symptom — three questions that cost less than one restart.

Q · You have been editing, restarting and re-trying for an hour and the error is still there. What should you have done instead, and how do you start doing it now?
Reproduce It First

A bug you cannot reproduce cannot be shown fixed. Before hypotheses, get the failure to happen on demand — the exact input, state and environment — and write down the recipe, because the recipe is the test the fix has to pass.

Q · A customer says checkout failed, you try it and it works. What do you do before forming any theory about the cause?
The Minimal Reproduction

Once the failure reproduces, remove everything that is not needed for it to keep failing — the UI, the real provider, the other tables, the framework — until what remains is small enough that the cause has nowhere to hide.

Q · The bug reproduces inside the whole store, with the UI, the API, the provider and the database all involved. How do you find out which of them actually matters?
Binary Search Over the System
▶ lab

Frontend or backend? Backend or database? Before commit X or after? Every debugging question that splits the candidate space in half is worth asking before any question that removes one candidate — and git bisect is the same move applied to history.

Q · The bug could be in any of five layers or any of forty commits. Which question do you ask first so that each answer removes the most candidates?
Logs Are Evidence, Not Thinking

A log line is an observation that was cheap to make in advance. It supports or kills a hypothesis; it does not generate one. "Add more logging" is only a plan when you can say which hypothesis the new line would distinguish.

Q · You have thousands of log lines and no idea what caused the failure. What is logging for, and how do you use it without drowning in it?
Reading the Error Message

An error message answers four questions if you let it: what failed, where, with what input, and which assumption broke. Searching the exact string first skips all four and hands your hypothesis to whoever wrote the top result.

Q · A stack trace is on the screen. What do you read before you search for it, and what does each part tell you?
Predict Before You Look

Before changing code or making an observation, say what you expect to see if your hypothesis is right and what you expect if it is wrong. The prediction is what turns a change into an experiment and stops "it looks fine" from meaning anything you like.

Q · You are about to make a change or check a log. What sentence should you write first, and what does writing it protect you from?

Reading & Reverse Engineering Code

5 lessons

An unfamiliar codebase: entry point, follow the data, find the state, find the side effects, understand the boundary. Not "read every file".

Reading a Codebase

README, entry point, one main feature end to end, the dependencies it pulls in, the data model it touches, and the tests that describe it — in that order, and stopping when the question you came with is answered. Not every file.

Q · You have just been given access to a repository you have never seen and a task inside it. Where do you start reading, and when do you stop?
Debugging Code You Did Not Write

Find the entry point, follow the data, find the state, find the side effects, understand the boundary. Five questions that turn an unfamiliar failing system into a path you can put observations on — without first understanding all of it.

Q · Something is failing in code you have never read and there is no time to learn it all. What do you find first, and in what order?
Reverse Engineering a System

Where does the program start? What receives input? Where is data stored? Which modules change state? What external systems exist? Five questions recover the design of a system whose design was never written down — from the running thing, not the folder names.

Q · You have inherited a system with no documentation and no author to ask. How do you recover what it is and how it works, without reading all of it?
Follow the Data

Pick one value — an order, a price, a cart — and follow it from where it enters to where it rests, through every transformation and hand-off. Code is organised by module; behaviour is organised by data, and following the data reads the code in the order it actually runs.

Q · You need to know what happens to a piece of data between the request and the database, and the code is spread across a dozen files. How do you read it in the order it runs?
Before You Copy Code

A snippet from documentation, a search result or an assistant is a proposal, not a solution. Before it goes in: what does it do, why does it work, what does it assume, and how does it fail? Four questions that take minutes and are the difference between using a tool and being used by it.

Q · You have found code that appears to do what you need — in the docs, a forum, or an AI answer. What do you establish before pasting it into the store?

Reading Documentation

5 lessons

Goal, relevant concept, minimal section, try the example, modify it, apply. Documentation before tutorials, tutorial dependency, and search as a skill.

Reading Documentation With a Goal

Documentation is consulted, not read. Start from the goal, find the concept that owns it, read the smallest section that answers it, run the example, change the example until it breaks, then apply it to your problem — and stop reading the moment the next step is obvious.

Q · The library you need has three hundred pages of documentation and you need one thing from it. How do you read enough — and only enough — to get that thing working in your own code?
Documentation Before Tutorials

A tutorial shows one path through a tool, chosen to be watchable. Primary documentation states the contract. Read the contract for anything your system will depend on, and use tutorials for what they are good at: orientation, vocabulary, and seeing the pieces connect once.

Q · When you meet a technology for the first time, what should you read first — the primary documentation or a tutorial — and what does each one actually give you?
A Reading Strategy for an Unfamiliar Library

Given a library's documentation and no prior knowledge, find five things and stop: how to install it, the one abstraction everything else is built on, one API call you can run, what it does when something goes wrong, and one limitation that would matter in production.

Q · You have been pointed at an unfamiliar library's documentation and told to evaluate it by tomorrow. What are the five things you must find before you have read enough, and how do you find each one?
Tutorial Dependency

If you can only build what a tutorial builds, you have not learned the tool; you have learned the tutorial. The way out is a ladder: follow it, modify it, build something similar without it, then build from requirements alone — and the last rung is where the understanding is tested.

Q · You have followed a dozen tutorials and can reproduce each one, but a blank requirement leaves you stuck. How do you tell tutorial fluency from understanding, and how do you get from one to the other?
Search as a Skill

"My code no work react" finds nothing; "React stale closure useEffect interval" finds the answer in the first result. The query is a compressed statement of what you understand about the problem, and evaluating what comes back — authoritative, current, your version, explains why — is the second half of the skill.

Q · Something is broken and you are about to search for it. What makes one query find the answer and another find nothing, and how do you decide which of the results to believe?

Researching Unknown Technology

6 lessons

"What is Redis?" Do not read everything. What problem does it solve, what does it guarantee, what is the simplest example, how does it fail, what are the alternatives.

Researching an Unknown Technology
▶ lab

"What is Redis?" Do not read everything. Ask why you might need it, what problem it solves, what it guarantees, what the simplest example is and how it fails. Five answers on one page beat a weekend of reading, and they tell you what to learn next — or that you do not need to.

Q · A technology you have never used keeps coming up — in a code review, a job posting, a colleague's suggestion. How do you research it in an afternoon and come out with a decision rather than a vocabulary?
What Problem Does It Solve?

Every technology exists for one problem, and the question that cuts through its feature list is which. Ask it of the tool, then ask whether your system has that problem — and if the two do not match, no amount of the tool's other virtues makes it the right choice.

Q · Someone proposes a technology and lists its advantages. What single question tells you whether any of those advantages apply to your system?
Evaluating a Technology
▶ lab

A technology evaluation has six parts: the problem it solves, its mental model, its guarantees, its costs, its failure modes and its alternatives. Filled in honestly for two or three options — including the one you already have — it decides; filled in for one option, it advocates.

Q · You have narrowed a need to a few candidate technologies. What does an evaluation have to contain to actually decide between them, rather than confirm the one you already liked?
Guarantees and Failure Modes

Read a technology for what it promises and what happens when the promise cannot be kept. "Fast" and "reliable" are not guarantees; "a write acknowledged is durable across restart" is, and "the most recent writes may be lost on crash" is the failure mode that goes with it. Your design depends on which one you assumed.

Q · A technology says it is fast, reliable and scalable. What are the actual guarantees hiding behind those words, and what does your system do when each one fails?
Evaluating What the Search Returned

A search returns claims, not answers. Four checks turn a claim into something you can build on: is the source authoritative for this tool, is it current, does it match your version, and does it explain why. A result that fails the fourth is a patch, and the first three decide whether it is even a correct one.

Q · Your search returned a confident answer with a code block. Before you use it, what do you need to know about where it came from, and how do you find out in a minute?
The Smallest Experiment With a New Technology

Told to add video calls, the reflex is to learn WebRTC's API. The move is to ask what problem it solves, which of its concepts your problem touches, and what the smallest experiment is that proves the pieces connect for you — and to build that, not the feature, first.

Q · You have been asked to add a capability that needs a technology you have never touched. What is the smallest experiment that tells you whether it will work for your problem, and how do you find it without first learning the whole thing?

Asking Better Questions

4 lessons

From "how do payments work?" to "which system should be authoritative for whether an order has been paid?" — questions that reduce uncertainty, and how to ask people.

Asking Better Questions

"How do payments work?" cannot be answered in a way that changes what you build. "Which system should be authoritative for whether an order has been paid?" can. The move is rewriting the question until an answer would decide something.

Q · You are stuck on payments and the only question you can form is "how do payments work?" — how do you turn it into one whose answer changes what you build next?
The Question Quality Ladder
▶ lab

A question is vague, researchable or decisive, and the difference is checkable: does it name a component, name a boundary, ask for a mechanism, scope itself to my system, and ask for a decision? Five criteria, applied to your own questions before you send them anywhere.

Q · How can you tell, before you spend an hour on it, whether a question is one that can be answered — and whether its answer will decide anything?
Questions That Reduce Uncertainty

Among all the questions you could ask, the one worth asking next is the one whose answer removes the most uncertainty per hour spent — and a question is an experiment, with a cost, an expected answer, and a decision that depends on it.

Q · You have many open questions and limited time — which one do you ask next, and how do you know it was worth asking?
Asking People

A stakeholder, a senior, a provider's support desk: each can answer in minutes what would take you days — if the question arrives with what they need. Bring the expected, the actual, the evidence and your hypothesis, so the answer is usable and so the asking is not delegating your understanding.

Q · When the fastest route to an answer is another person, what do you bring so that their answer is usable — and so that asking does not replace your own understanding?

Trade-Off Analysis

6 lessons

Simplicity, performance, reliability, cost, security, time, maintainability. Matrices without fake precision, reversible against irreversible, deciding under uncertainty.

Trade-Off Thinking

"Which is better?" has no answer; "better at what, and worse at what?" does. Every engineering choice moves along simplicity, performance, reliability, cost, security, time and maintainability at once, and the move is naming which ones this decision actually touches before comparing anything.

Q · Two designs are on the table and the argument has gone round three times — how do you turn "which is better?" into a question with an answer?
Trade-Off Dimensions

Simplicity, performance, reliability, cost, security, time, maintainability — each is a question you can ask of a design, with an observation that would answer it. The move is turning the axis names into questions for your system, and noticing which questions this decision does not change.

Q · The seven trade-off axes are just words until they are questions about your system — what does each one actually ask, and how do you tell which ones a given decision moves?
The Trade-Off Matrix, Without Fake Precision
▶ lab

A matrix of options against axes is useful for seeing which axis the argument is really about — and dangerous the moment the numbers are added up. Monolith against microservices on simplicity, scale and operational cost, scored as positions rather than measurements, with the caveat the numbers cannot contain.

Q · A trade-off matrix looks like rigour — when does it actually help, and how do you use one without letting made-up numbers make the decision?
Reversible vs Irreversible Decisions

Renaming an internal function costs a minute to undo; a public API, a database schema, a partition key and a cloud architecture cost progressively more — some of them almost everything. Spend decision effort in proportion to the cost of reversing, and make the expensive ones as late and as small as you can.

Q · Every decision gets the same meeting — how do you tell which ones deserve it, and which ones you should just make and move on?
Deciding Under Uncertainty

The evidence is not in and the decision cannot wait. The move is not to guess harder: take the current evidence, make the best choice that is cheap to reverse, build the feedback that would tell you it was wrong, and adjust — a loop, not a bet.

Q · You have to decide now and you do not know enough — how do you decide in a way that gets better instead of just hoping?
The Decision Journal
▶ lab

A decision written down with the evidence, the alternatives, the reason, the assumptions and when to revisit is a decision that can be re-made on purpose. One that lives only in the code is re-argued every time the code surprises someone.

Q · How do you record a decision so that, when the requirement changes, the next person can tell whether the decision still holds — without re-fighting it?

Estimation & Ordering

4 lessons

Estimation as decomposition, uncertainty communicated instead of hidden, the riskiest unknown first, and what to build first.

Estimation as Decomposition
▶ lab

"This will take two weeks" is a feeling about a list you have not written. Break the store into product model, cart, checkout, payment, testing and deployment, estimate each with a range, and the number becomes something you can defend — and revise.

Q · Someone asks how long the store will take. What do you do before answering, and what makes the answer more than a guess with a unit on it?
Communicating Uncertainty
▶ lab

A range you know and a point you say is a lie by rounding. Estimates should carry their uncertainty — what is known, what is assumed, what has not been discovered yet — in a form the listener can plan with, without false precision and without hiding behind "it depends".

Q · You have a decomposed estimate with wide pieces in it. How do you tell someone who needs a date, without either inventing precision or refusing to answer?
Risk-First Development
▶ lab

When everything is easy except one thing, the one thing decides the project. Prototype the payment integration before polishing product cards — not because payment is most valuable, but because it is the piece whose answer could change everything else.

Q · One piece of the system is unfamiliar and the rest is routine. Where should the first week go, and what does "risk" actually mean when choosing?
What to Build First
▶ lab

Dependency, risk, user value and learning value — four questions asked of each piece, and the first vertical slice falls out. One possible sequence for the store, and the other sequences that are also right, and when.

Q · The decomposition is done and everything is on the list. Which piece is first, which is second, and what makes an order defensible rather than habitual?

Build vs Buy

4 lessons

Is this core differentiation, can a provider solve it, what does integration cost, what does operating it cost, what happens when the provider fails.

The Build-vs-Buy Questions
▶ lab

Before "should we build payments ourselves?" can be answered, five questions have to be: is this our core differentiation, can a provider solve it, what does integrating cost, what does operating it cost, and what happens when the provider fails. The answers are the decision; the slogan is not.

Q · A capability the store needs — payments, email, search, image storage — could be built or bought. What do you ask before deciding, and why is "it would be faster to use a service" not yet an answer?
Core Differentiation

"Core" does not mean important; payment is essential and nobody chooses a store for it. Core means the reason a customer picks you — and that is the one thing you cannot buy, because a provider that solves it solves it for your competitors too.

Q · Everyone agrees the "core" of the system should be built in-house. How do you find out what the core actually is, and why is the answer so often not what the engineers think?
Integration and Operating Cost

"Build" is estimated for the week it takes; "buy" is estimated for the SDK call. Both are wrong the same way: the cost of a capability is what it takes to connect it and what it takes to live with it, and neither appears in the first estimate.

Q · Two options meet the requirement: build it, or integrate a provider. What are the costs that the obvious estimates leave out, and how do you find them before they find you?
When the Provider Fails

Every bought capability will fail, be slow, change under you, or rate-limit you — not as a possibility, as a schedule. The build-vs-buy decision owes the design a paragraph for each, and the payment provider and the email provider need very different paragraphs.

Q · You have decided to buy payment and email. What does the store do while each of them is down, slow, changed or throttled — and which of those four does the design actually have to survive?

Iterative Development

7 lessons

Implementation order, dependency-first and value-first, architecture that emerges from requirements, and the complexity ledger every new component must answer.

Iterative Development

Change → run → observe → fix, in loops small enough that each one teaches something. A system is grown from one that already works; scale is added after a working system and a measured bottleneck, not before either exists.

Q · You have a plan for the whole store and it will take weeks before anything runs end to end. How do you turn that plan into loops that each produce evidence, and when — precisely — does scaling belong in one of them?
Implementation Order
▶ lab

Product model → display products → cart → checkout without payment → order persistence → payment → failure handling → admin: one defensible sequence for the store, with the reason for each step. Not the only sequence — and the device says so.

Q · The store is decomposed into pieces and you can build any of them. Which do you build first, in what order, and how would you defend the order to someone who would have chosen differently?
Dependency First

If B requires A, build or understand A first. Obvious when said, skipped constantly in practice: checkout built before the cart exists, payment integrated before anyone knows what an order is, a feature started on top of a concept nobody has understood.

Q · You are about to build something and part of it depends on something else that does not exist or that you do not understand. How do you find the dependency before it finds you, and what do you do about it?
Value First

When the dependencies permit, build the thing a user could actually use. A store that shows products and takes orders without payment is usable in a way that a perfect cart on top of nothing is not. Contested — against building the riskiest thing first — and this lesson says how.

Q · Several pieces are buildable now and none depends on the others. Which one do you build, and how do you choose between the one a user could use today and the one that would tell you whether the project is feasible?
Architecture From Requirements
▶ lab

Need persistence → a database. A browser interface → a frontend. Logic the client must not control → a backend. Payment → an external provider. Result: Browser → Backend → Database, plus the provider. Every box has a requirement that put it there, and no box is there without one.

Q · You have the requirements for the store and a blank page where the architecture goes. How do you derive the boxes from the requirements — and how do you tell a box that a requirement put there from one that a habit did?
Add Complexity Only When Required
▶ lab

Single server and database. Repeated expensive reads → maybe a cache. Long-running work in the request → maybe a queue and a worker. Each "maybe" waits for the symptom it treats; complexity should have a reason, and the reason should be something you observed.

Q · The store runs on one server and one database, and you can already see the components it will need eventually. When does "eventually" arrive for each one, and what has to be true before you add it?
The Complexity Ledger
▶ lab

Every new component answers three questions in writing: what problem does it solve, what complexity does it introduce, what happens if it fails. A component that cannot answer all three is not yet justified; one that can is accountable for as long as it lives.

Q · Someone proposes adding a component to the store — a cache, a queue, a search engine, a second service. What must be written down before it goes in, and what does that record let you do later that nothing else does?

Learning Without AI

6 lessons

Your understanding, your decomposition, your pseudocode, your attempt — then hints one rung at a time. Explain it back, build from memory, find where you hesitate.

Learning Without AI
▶ lab

In this mode the AI does not write solution code. It may ask questions, explain a concept, review your reasoning, give a hint, or point at the documentation — everything except the part that would replace your attempt. The rule is about what is delegated, not about the tool.

Q · You want to learn to build things, and you have a tool that will build them for you. How do you use it so that you end up able to build the next one — and how would you know whether you can?
No AI on the First Attempt
▶ lab

Problem → your understanding → your decomposition → your pseudocode → your attempt → then ask for help. The order is the lesson: help given after an attempt corrects it; help given before one replaces it.

Q · You are facing a problem you have never solved and a tool that would solve it in seconds. What do you produce before you ask, in what order, and why does the order matter more than the quality of what you produce?
The Hint Ladder
▶ lab

Hint one: the conceptual direction. Hint two: the relevant abstraction. Hint three: pseudocode. Hint four: a partial implementation. Then the reference. Each rung gives less than the next, and the rung you stop at is the measure of what you still own.

Q · You are stuck after an honest attempt, and you want help that unblocks you without taking the problem away. What are the rungs of help, how do you ask for one at a time, and how do you tell that you took one too many?
Explain It Back

Explain it in your own words, draw it, apply it to a case it was not explained with. Three checks that turn "I read it and it made sense" into evidence — and that fail, usefully, exactly where understanding stops.

Q · You have read an explanation — of webhooks, of idempotency, of a data model — and it made sense. How do you find out whether you understood it or only followed it, before the difference costs you?
Build From Memory

Close the reference. Rebuild the core idea from nothing. Compare with the reference. Fix the understanding, not the code. The differences are the only precise map of what you did and did not learn.

Q · You have built something with a reference open — a tutorial, a generated solution, a colleague's code — and it works. How do you find out how much of it you could build again, and what do you do with the answer?
The Feynman Check

Can you explain it simply? Where do you hesitate? Which term are you hiding behind? The hesitation is not a failure of nerve — it is the most precise locator of a gap in understanding there is, and the term you reach for is the gap's name.

Q · You believe you understand something and you want to find the exact place where you do not. How do you use a simple explanation as an instrument, and what do you do with the place it points at?

Using AI Without Losing Understanding

7 lessons

Think, form the question, use the tool, understand the answer, verify. AI as reviewer and debugging partner, the dependency check, and what you still own.

Good Tool Use

Problem → Think → Form Question → Use Tool → Understand Answer → Apply → Verify. The tool is in the middle of the sequence, not at the start of it — because a question you have not formed produces an answer you cannot judge.

Q · You have an AI assistant open next to the editor and a problem you do not understand. What is the sequence that uses the tool well, and how do you tell it apart from the one that only looks like it?
AI as Reviewer

Your design → AI critiques → you decide → you implement. The assistant is strongest as a second reader of something you made, because then its output is a list of objections you can judge, not a design you have to adopt.

Q · You have a design for a piece of the system and an assistant that will happily produce one of its own. How do you use it to make your design better without ending up with its design instead?
AI as Debugging Partner

Before the assistant can help with a bug, you must bring four things: expected behaviour, actual behaviour, evidence, and a hypothesis. Bring fewer and it guesses; bring all four and it investigates with you.

Q · Something is broken and you want the assistant's help. What do you have to bring to the conversation for its help to be investigation rather than guessing, and how do you know the difference?
The AI Dependency Check
▶ lab

Four questions about any code the assistant helped with: could you explain it without the tool, recreate its core idea, describe its failure modes, and debug it yourself? Where the answer is no, go one layer deeper — that layer is yours now, whether you understand it or not.

Q · Code the assistant wrote is in your system and it works. How do you find out whether you understand it well enough to own it, and what do you do about the parts you do not?
If You Are Nothing Without the LLM

"If you are nothing without the LLM, you should not have it." Read constructively: the tool should amplify an engineering ability that exists, not stand in for the understanding required to own the result. The strongest opposing view — that fluency with the tool is itself the new skill — is stated and taken seriously.

Q · What does it mean to be "nothing without the LLM", how would you tell whether it describes you on a given piece of work, and what does the sentence actually ask you to do?
What You Still Own

The assistant can produce code, architecture, SQL, tests and explanations. You still own requirements, correctness, trade-offs, security, failure handling and understanding — the things that need to know what the system is for, and the things that are yours when the output is wrong.

Q · The assistant can produce almost every artefact in the project. What is left that is yours, why is it yours rather than a gap in the tool, and how do you make sure it gets done?
The Engineering Notebook
▶ lab

Current goal, assumptions, unknowns, decisions, experiments, findings, next step. A notebook in your own words is where independent reasoning is built — and where you can see, at a glance, whether the tool has been doing yours.

Q · How do you keep your own reasoning about a problem in one place so that it accumulates, survives a day off, and can be checked against what the assistant produced?

Problem Solving Across Domains

7 lessons

How the loop enters DSA, databases, backend, frontend, system design, ML and agentic engineering — the same questions, different next lessons.

Problem Solving and DSA

Problem → Constraints → Pattern → Algorithm. The algorithm is the last step, and the step people start from. The constraints — how much data, how often it changes, what "fast enough" means — are what pick the pattern, and the pattern is what picks the algorithm.

Q · A piece of the store needs an algorithm and you do not know which. How does the problem-solving loop get you from the requirement to the right one, and what does it hand off to the DSA domain?
Problem Solving and Databases

Data → Access Patterns → Model → Index → Query. The database domain teaches models, indexes and query plans; this lesson is the step before — discovering that there is data, how it will be read and written, and only then which model and which index.

Q · The store has data and you need a schema. How does the loop get from plain-English requirements to a model you can hand to the database domain, and what decides the indexes before any query is slow?
Problem Solving and Backend

User Workflow → Request → Business Rules → State → Dependencies. The backend is where the workflow becomes a request, the request meets the rules, the rules change state, and the state depends on things outside the process. Each arrow is a question; the backend domain answers them.

Q · A workflow in the store has to become an endpoint. How does the loop get from "the customer checks out" to a request whose rules, state changes and external dependencies are all named, and what does it hand to the backend domain?
Problem Solving and Frontend

User Goal → Interaction → State → UI. The screen is the last step. What the user is trying to do, the interactions that get them there, and the state each interaction reads and changes come first — and they decide the UI far better than a component library does.

Q · A screen in the store has to be built. How does the loop get from what the user wants to the state the screen holds and the interface that shows it, and what does it hand to the frontend domain?
Problem Solving and System Design
▶ lab

Requirements → Scale → Bottlenecks → Architecture. Architecture is the last step, and the reflex starts there. The requirements say what must hold; the scale says how much load; the bottleneck is what actually breaks first under that load; the architecture is the smallest change that relieves it.

Q · The store has to "scale". How does the loop get from that word to an architecture decision with evidence behind it, and what does it hand to the architecture and distributed-systems domains?
Problem Solving and ML

Business Problem → Target → Data → Metric → Model. The model is the last step, and the one the word "AI" makes people start from. The target is what you are actually predicting, the data is whether you can, the metric is what "good" means to the business — and the ML domain teaches each once they are named.

Q · Someone wants to "use ML" in the store. How does the loop get from that request to a formulated problem with a target, data, and a metric — or to the finding that ML is not the answer — and what does it hand to the ML domain?
Problem Solving and Agentic Systems

Agentic architecture should emerge from requirements, the way any architecture should. Do not start with a multi-agent system; start with one deterministic workflow and ask, at each step, why it is insufficient. The answer names the one place an agent is needed — or finds that none is.

Q · Someone wants the store's support assistant to be "agentic". How does the loop get from that word to a workflow with a reason for every non-deterministic step, and what does it hand to the agentic-engineering domain?

Case Studies

7 lessons

An online store, a chat app, a URL shortener, file upload, search, an analytics dashboard, an AI assistant — each started from one sentence, each grown only as far as its requirements justify.

Case: Build an Online Store
▶ lab

One sentence — "build an online store" — taken from actors and actions through data, state, interfaces, a walking skeleton, the cart decision, checkout in pseudocode, payment research, failure cases, and scale only on evidence. The whole loop, on the running example, with nothing added before it was needed.

Q · You have "build an online store" and nothing else. How do you grow it from a sentence into a system, and how do you know at each step that the next piece was justified rather than merely available?
Case: A Chat App

"Users send messages to each other" → Users, Conversation, Messages, Participants → Send, Store, Retrieve, Realtime, Read State. The word "realtime" is the unknown; the decomposition puts it fourth, and the first version works without it.

Q · You are asked for a chat app and the word "realtime" is doing most of the work in the request. How do you decompose it so that realtime is one capability among six rather than the whole problem?
Case: A URL Shortener

Long URL → Short Code → Redirect. The first version is one table and two endpoints; the interesting engineering arrives only when the requirements do — uniqueness under concurrency, read-heavy traffic, click logging — and the ladder for "we need a distributed ID generator" ends somewhere much smaller.

Q · The URL shortener is the system-design interview's favourite, so you already know the "final" architecture. How do you build the first version without it, and what would have to be measured before any of it is justified?
Case: A File Upload Service

Upload, Storage, Metadata, Permissions, Download. The first version streams through the server; the requirement that changes the shape is size, and the prototype question — can the browser upload a large file directly to object storage? — is answered in an afternoon before any architecture depends on it.

Q · You need to let users upload files, and someone says "just use object storage". What are the five capabilities, which one forces the architecture, and what is the smallest prototype that tells you whether the browser can talk to storage directly?
Case: Search Products by Name

"Search products by name" is a SQL query until a requirement says otherwise. The case runs the why ladder for Elasticsearch honestly: the first version is a filtered query, the second is a database full-text index, and a dedicated search engine is justified by requirements the store may or may not ever have.

Q · The store needs "search products by name", and the first suggestion is a search engine. What is the sequence of solutions from a WHERE clause upward, and which requirement moves you from one to the next?
Case: An Analytics Dashboard

Metric, Source, Aggregation, Freshness, Visualization. "We need a dashboard" is a request for a chart; the requirement is a metric someone will act on, with a definition, a source and a freshness that decide whether the first version is a query against production, a nightly summary table, or a pipeline into a warehouse.

Q · The founder wants "a dashboard for the store". How do you find the metric behind the chart, and which of its properties — definition, source, aggregation, freshness — decides how much data engineering the first version needs?
Case: An AI Assistant for Company Documentation
▶ lab

"Answer questions about company documentation" → Documents, Retrieval, Context, Model, Answer, Evaluation. The first version is retrieval plus one prompt, measured against a question set; the why ladder for "we need a multi-agent system" ends at a retrieval fix most of the time — and says when it would not.

Q · You are asked for an assistant that answers questions about internal documentation. What are the six capabilities, which one do people skip, and what would have to be true before "we need agents" is the right next move?