SlicesSTAGE-SPECIFICGENERALILLUSTRATIVE

The Walking Skeleton

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.

The situation, the reflex, and why it stalls

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

The question

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 situation

Day one of the store. You have a decomposition, a first slice in mind, and a fresh repository. You could start on the product page — but you also do not yet know whether the framework talks to the database, whether the deployment works, or whether the API and the page even run in the same place.

The reflex

Set up the project properly. Install the framework, configure the database client, set up linting and tests, write the models, get the folder structure right. Then features will go quickly, because the scaffolding is solid.

Why it stalls

The scaffolding is configured against no feature, so its correctness is unknown until a feature runs — and the first feature discovers the database URL is wrong in production, the API and page are on different origins, and the test runner cannot see the database.

What the reflex produces — and fails to produce
  • The scaffolding is configured against no feature, so its correctness is unknown until a feature runs — and the first feature discovers the database URL is wrong in production, the API and page are on different origins, and the test runner cannot see the database.
  • Setup expands without a stopping rule. Auth scaffolding, an ORM, a component library, CI — all reasonable, none proven, each one another thing that could be the reason the first feature fails.
  • The first feature becomes the first integration test of the entire environment as well as of itself, so when it fails nobody knows whether the feature or the environment is at fault.
ProblemUnderstandRequirementsConstraintsUnknownsDecompositionSmallest StepModelExperimentObserveDebugLearnIterate

The move

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

  • Build the thinnest path through every layer that will exist, with the least possible content, and get it running where it will run. A page that calls an endpoint that reads one row from the database and shows it. Nothing configurable, nothing reusable, nothing pretty.
  • Include every boundary the real system will cross — browser to server, server to database, and the deployment — and exclude every feature. The skeleton is about connections, not capabilities.
  • Deploy it. A skeleton that only walks on a laptop has not proved the boundary that fails most often. If deployment is a week away, the skeleton is not done.
  • Then grow features onto it slice by slice (Vertical Slices). Every later slice inherits a proven path and only has to prove itself.

The skeleton as a slice

The thinnest slice there is, written in the slice device. Each layer does the least thing that constitutes crossing it. The required last line is longer than usual, because a skeleton proves almost nothing on purpose.

The store's walking skeleton
A page shows one value that came from a database row, in the deployed environment
  1. BrowserLoads one page, fetches one route, prints one string.
  2. APIOne route that runs one query and returns one field.
  3. DatabaseOne table, one row inserted by hand.
  4. Browser againReceives the response and shows it; that is the whole observation.
  5. DeploymentThe same path, in the environment where the store will live.
proves
The browser can reach the API; the API can reach the database; the deployment configuration works for all three; the environment is not the reason the next slice fails.
does not prove
Any feature at all. Not products, not that the row shape is right, not auth, not errors, not performance, not that the page works for a user-supplied id. It is a heartbeat, not a store.

Every boundary, once

The skeleton's content is arbitrary; its shape is not. It must cross every boundary the real system will have. The diagram is the store's; the chat app's would add a persistent connection, and the file-upload service's would add object storage.

GET /products/1select one rowthe rowJSON → printedBrowserDeployed environmentAPI routeDatabase (one row)
UserLLMAgentToolDataDecisionHumanGuardrail

Building it, and stopping

The skeleton is short enough to be a pipeline with a hard stop. The failure column is mostly one failure: not stopping.

Walking skeleton
  1. 1
    List the boundaries

    Browser–server, server–database, deployment; plus any external system already known to be in V1.

    fails by Listing features instead of boundaries.

  2. 2
    Choose the least content

    One row, one field, one route, one page.

    fails by "While I am here" — a real product model, a component library.

  3. 3
    Cross each boundary once

    Write the least code that makes the request travel the whole path.

    fails by Adding auth, validation or error handling; each is a feature, not a connection.

  4. 4
    Deploy

    Run the same path where the system will live.

    fails by Declaring it done on a laptop; the environment boundary is the one that fails most.

  5. 5
    Stop

    Write down what was skipped; hand the proven path to the first slice.

    fails by Growing the skeleton into the MVP without ever choosing a slice.

How to do it

Most important first.

  • List the layers and boundaries the system will have: browser, API, logic, database, and anything external you already know about. The skeleton must touch each once.
  • Choose the content to be the least that can be observed: one row, one field, one route, one page with one value on it.
  • Skip everything that is not a connection: no auth, no validation, no styling, no error handling beyond the framework default. Write each skip down.
  • Run it in the real environment before calling it done (Short Feedback Loops).
  • Keep it: the skeleton's route becomes the health check, or the first product slice replaces it directly.

Worked on a concrete problem

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

  • The store's skeleton: a products table with one row inserted by hand; GET /products/1 returning it as JSON; a page that fetches that route and prints the name; deployed to wherever the store will live. Four hours including the deployment, which found that the production database needed a different connection string — a discovery worth exactly four hours and not four weeks.
  • What it proved: the framework serves pages and API routes together; the database is reachable from the server in both environments; the page can call the API from the browser (so cross-origin is settled); deployment works. What it did not prove: anything about products, carts, checkout, auth, or how the system behaves with real data or real users.
  • The chat app's skeleton, for contrast: one message inserted by hand; a websocket that pushes it to a connected browser; the browser shows it. The extra boundary — the persistent connection — is in the skeleton because it is the one most likely to fail in deployment, and the skeleton's job is to cross every boundary once.

How you know it worked

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

  • A URL exists, in the real environment, that shows a value that came from a database row.
  • You can name every boundary the skeleton crossed, and every one the real system will have is on the list.
  • The first feature slice was smaller than expected, because the path was already open.

The questions you can now ask

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

Next questions
  • ?Which boundaries will this system cross, and has each been crossed once, with the least possible content?
  • ?Does the skeleton run where the system will run — and if not, what is stopping it?
  • ?What did I skip to keep it thin, and is each skip written down?
  • ?What is the first real slice to grow onto it?

What can go wrong

How the move itself fails
  • The skeleton grows flesh: "while I am here" adds auth, a component library and an ORM, and the skeleton becomes the scaffolding it was meant to replace, unproven by any feature.
  • The skeleton skips a boundary — usually deployment or the real database — and proves connectivity only in the environment that was never in doubt.
  • Mistaking the skeleton for the first slice. It shows a hard-coded row; it is not "show one product" until the row is real and the id comes from the user. Both are valid; confusing them means the first feature is never actually built.
What the move costs
  • The skeleton is throwaway-shaped — a hard-coded row, a page that prints a string — and it is tempting to skip it because nothing in it survives. What survives is the proven path, which is not visible in the code.
  • Deploying on day one costs the deployment setup on day one, before anyone has asked for a deployment.
Misreads
  • "The skeleton is the MVP." An MVP proves the idea to a user; a skeleton proves the connections to the builder. The skeleton shows nothing a user would want (MVP Thinking).
  • "Set up everything properly first, then the skeleton." The skeleton *is* the setup, tested. Setting up more than the skeleton needs is scaffolding against imagined needs, which is the reflex.

Where this applies

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

  • STAGE-SPECIFICOn a greenfield system the skeleton is the first thing built; in an existing system the skeleton already exists and the move becomes finding the thinnest path through it that touches every layer a new feature needs — the same idea, applied to a change rather than a system.
  • GENERALCrossing every boundary once with minimal content applies to any system with boundaries — a CLI that reads a file and writes one, a pipeline that ingests one record and emits one row.
  • ILLUSTRATIVEThe four hours, the connection string and the chat app's websocket are invented for the example; the boundaries a real system crosses are its own.

Where the depth lives

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