Four weeks into a project, we had automated 70% of our order approvals. Sounds great. Except we could have automated 35% of them in five days, and we didn’t.
That gap haunts me. Not because of the engineering. The engineering was fine.
It haunts me because of the five people on the order processing team who spent three extra weeks doing work that a computer could have done for them. And the sellers who waited days for their products to reach buyers, products they had poured weeks of effort into creating.
This is what happens when you build software from the inside out. You assemble each of the parts, then put them all together at the end.
It works. It’s logical. And it delays value for everyone.
There is a better way. Slice your features thin, end to end through every layer, and deliver them one at a time. You will ship value in days instead of weeks. You will reduce risk. And you will be amazed by what happens then.
Cockburn calls this a walking skeleton. The Pragmatic Programmers call this style tracer bullets.
How do you just start thinking in this daily habit?
One of the first things you can do is to armchair your features after you are done. When you have completed a feature, especially one that took longer than you expected, think about how else you could have rearranged the work, so that you could confidently share your work every day.
It may seem like you are playing armchair quarterback when you go back after you are done. The work is already complete, and now you have hindsight as your companion and colleague. Nonetheless, doing this exercise will help you start to think in smaller slices. It will start to change the way you think.
Learning this way is one of the fastest ways to master something new. Often called trial and error, we should think of it as trial and feedback.
Order Approvals: Four Weeks or Five Days
I was working with a marketplace for digital products. Once a purchase is approved, these products are available for immediate delivery. Sellers put sweat and tears into building these products. Weeks of effort distilled into something a buyer could access in seconds.
That instant delivery created a fraud problem. Someone buys a product with a stolen credit card, downloads it immediately, and the seller loses the product and the revenue. Their sweat equity just evaporated.
To fight this, the company put together a team to review every order before it was fulfilled.
As the business grew, so did the team, the workload, and the bottleneck. Buyers were waiting a day or two for products they were expecting instantly.
Buyers called the support line. Support escalated to the approval team. The approval team fell further behind. And sellers watched their hard work sit in limbo, waiting on a process they couldn’t see or control.
We put together a project to automate the review. We identified three rules:
- Rule 1 handled 15% of orders. It was complicated.
- Rule 2 handled 35% of orders. It was straightforward.
- Rule 3 handled 20% of orders. The complexity was somewhere in between.
Orders that didn’t match any rule would still go to human review. Together, the three rules would automate about 70%.
The team estimated three weeks. It took four. And during those four weeks, nothing changed for the humans doing the reviews. They were working harder, the orders were climbing, and there was no relief in sight.
After the project shipped, Phil and I sat down to dissect how it went. Here’s what the team actually built, in order:
Rule 1 first, the most complicated and risky. Then Rule 2 and Rule 3. Then the workflow change to split the order list into “needs review” and “already approved.”
This is bottom-up development. Build the parts, then assemble them. It’s logical. Developers think this way naturally. How can I build a system if I don’t have the parts?
Phil and I, who worked together on the project, asked a different question. How could we have delivered value sooner?
We came up with this approach:
- Split the order list into multiple views by status. Small work.
- Add the workflow hook, a no-op that sends every order to manual review, same as before. Nothing changes yet.
- Implement Rule 2. The simple one. 35% of orders now auto-approve.
- Implement Rule 3. Another 20%.
- Implement Rule 1. The hard one. The final 15%.
Steps 1 and 2 would have taken about three days. Step 3, another two. Within five days, 35% of orders would have been automated.
Five days to get 35% of sellers’ products into buyers’ hands without delay. Five days to lighten the load on customer support. Five days to give the order processing team some breathing room.
Instead, they waited four weeks for our original approach to build all of it at once.
The total effort is roughly the same either way. The difference is when value arrives.
Image Upload: Ten Days of Silence vs. Two Days of Progress
This example comes from a 3D space-planning application. Users designed and visualized physical spaces: floor layouts, furniture placement, signage, the works.
One feature let users place custom images into their 3D scenes. Grabbing an image from the asset library was easy. Getting a new image into the library was not. The original workflow required uploading through a separate web app, processing it through another application to create a 3D asset, then reloading the entire scene. Fine for one or two images. Unworkable when a layout redesign involved hundreds of new assets each month.
The team was asked to build a streamlined upload: trigger it from within the app, select an image, and have it appear in both the library and the scene immediately.
They estimated 10 to 15 days. I asked when we could see parts of it working. The answer: in 10 to 15 days.
Another all-or-nothing feature.
I started asking questions. How are you approaching the work? What’s the architecture? What comes first? What comes second?
The plan was for two developers to work “together”, with heavy air quotes. One would start at the database layer and build upward. The other would start at the UI and build downward. In about 7 to 8 days each, they’d meet in the middle and connect the pieces. That connection could take a day, or it could take a week.
I pulled Brandon aside. We talked through an alternative approach using thin slices through all the layers.
We found something we could demonstrate in about two days:
- Trigger the upload action from the UI.
- Hard-code a known image path from the user’s machine.
- Send the image to the server with no additional attributes.
- The server applies default processing, creates the 3D asset, and responds.
- On response, the app reloads the entire asset library, the same reload that happens at startup.
Ugly? Yes. Hard-coded? Absolutely.
But in two days, the entire pipeline was working end to end. Every slice after that replaced a hard-coded piece with a real one.
Scene Loading: Three Months in the Dark
Building a 3D application is like building any other software in some ways, and completely different in others. There’s a render loop that constantly redraws the scene. Separation of concerns and clean architecture still apply. But the visual nature of the work changes what “progress” looks like.
When we rebuilt this application, one of the first features was scene loading. A space in 3D is made up of layers: the shell (walls, floor, ceiling), fixtures (counters, tables, built-ins), sections with detailed layouts, display areas, and signage.
Loading and composing all of that took about three months to build.
And when it was done, loading a large scene took several minutes, slower than the application it was replacing. The new system was worse.
The team had worked incrementally, but their increments followed architectural layers. First, load all the data. Then convert it to domain models. Then download the 3D assets. Then render. Seeing anything on screen took over two months.
Along the way, features were added to keep the user informed while they waited: gray-boxing, then color-boxing, then white-boxing. Scene loading was rewritten, not refactored, twice.
After the project, I sat down with Marcus, the lead developer, to talk about what we learned and what we could have done differently. I had a hunch that “differently” might also mean “better.”
A single thin slice could have been: get the data for the shell, convert it to the domain model, download the one asset, and render it on screen.
Just the walls and floor and ceiling. Incomplete. Useless. Or is it?
That slice touches every layer:
- Data access
- Domain model
- 3D asset
- Rendering
Just enough of each layer for one thing. And once that one thing works, new possibilities open up.
A feature called screenshot, which generates an image of the 3D scene, could have been developed independently once the shell was rendering. That work could have started weeks earlier.
Performance would have been visible from slice one. Instead of building everything and then discovering it was slow, telemetry from the first slice would have shown where time was being spent. Was it data loading for fixtures? Asset loading for sections? We would have known early and adjusted early. We might have avoided a rewrite or two.
Think about what performance means for a developer’s daily life. If loading a scene takes four minutes, and you restart the app every fifteen minutes to test your work, that’s two hours a day spent watching a loading screen. Two hours. Every day. For months.
If performance had been addressed from the first slice, imagine that loading time was one minute instead of four. That’s ninety minutes back every day. Happier developers. Faster features. Less context switching.
A better application for the end user.
Store Locator: A Story Decomposed
I was on a team building a retail e-commerce site. The product owner described a Store Locator feature:
Users search by zip code or city and state. The five closest stores appear with address, phone number, and hours. A map shows the stores with zoom and pan. The regional manager’s name, phone, email, and photo are displayed. And if the user is logged in, pre-fill their address.
That’s not one feature. That’s seven.
My first instinct was to split it by layer: build the models and services in week one, then the UI in week two. This felt productive. Yet something felt off. I kept thinking.
Will the models I build in week one survive contact with the UI? What do I tell my product owner when he asks for a demo? That I’m 40% done? What does 40% done look like? And if a teammate offered to help, can I hand off any work?
The answers were “no” and “I don’t know.”
Instead, I figured out how to slice it into thin features, each one end to end:
- Search by zip code. Display stores with address and hours.
- Add search by city and state.
- Add a static map to results.
- Add zoom, pan, and navigation to the map.
- Display the regional manager’s name, phone, and email.
- Display the regional manager’s photo.
- Pre-fill search when the user is logged in.
After feature 1 shipped, I could have built features 2 through 7 in almost any order. Some could have been built in parallel. The product owner saw real progress after each one. At one point, he changed the order of the remaining work and dropped the idea of the regional manager’s photo. This was exactly the kind of feedback I wanted early, not late.
Thin slices were lighter to carry. I could think about search without worrying about maps or managers. The mental stack stayed small. The wins came fast. The feedback was real.
It’s not always easy to find the right slices. The key: what can you demonstrate to the user? If you can’t show it, it’s too thin. If it doesn’t go end to end through your system, it’s not a slice. It’s a layer.
The Pattern
Every one of these examples follows the same arc. My team built from the inside out, assembled the pieces at the end, and delivered value all at once, weeks or months after starting.
Each alternative approach slices thin, delivers end to end from the first few days, and creates options that the original approach never had.
The pattern is simple:
- Tell the story from the user’s perspective. What problem are you solving?
- For each part of the story, identify the simplest possible version.
- Map the parts to your software architecture.
- Implement a single thin strand through all the layers.
- Demonstrate your work. Ask for feedback. Adjust the plan.
- Implement the next strand.
Three loops drive this forward:
- A tight loop of developing and delivering a strand.
- A medium loop of getting feedback and adjusting course.
- An outer loop of deciding whether to keep going or stop.
You don’t need to define “done” on day one. You set a direction. You implement the simplest version. You get feedback. Seeing the solution, you decide the next step. Seeing all the steps together, you decide whether to continue or stop.
Think about a suspension bridge. The strength to support lanes of traffic over a mile of open water does not come from a single thick cable. It comes from many long, thin strands, all working together.
Working in long, thin slices gives you the strength to keep your project above water.
“But Wouldn’t It Be More Efficient To Just Build It All At Once?”
I hear this one the most. And on the surface, it makes sense. If you already know what you’re building, why not just build it?
Three reasons.
First, you don’t know what you’re building. You think you do. But the moment users see working software, priorities shift. Features get reordered. Some get cut entirely.
Every story in this article includes a moment where the team could have changed direction, if we had delivered something sooner. When you build it all at once, you’re betting that your understanding on day one is still correct on day twenty. It rarely is.
Second, the “efficiency” of building everything at once is an illusion created by ignoring what happens to everyone else while you build.
The order processing team worked overtime for three extra weeks. Developers stared at four-minute loading screens for months. Efficiency measured only in developer keystrokes misses the cost carried by everyone waiting for value that could have arrived sooner.
Third, small batches surface bugs faster. When you deliver one slice and something breaks, you know exactly what changed. When you deliver four weeks of work and something breaks, debugging becomes archaeology.
The DORA research is clear on this: teams that work in small batches have lower change failure rates and faster recovery times. The time you think you’re saving by batching gets eaten by the debugging you create.
“I’ll Build The Full API While I’m Already Here”
This is YAGNI dressed in work clothes. You Aren’t Gonna Need It.
Building the full API feels efficient because you’re already in the code. You already have context. Why not build the other three endpoints while you’re at it?
Because every endpoint you build before it’s needed is a bet. You’re betting that the shape of the API won’t change when real users arrive. You’re betting that the time spent building, testing, and maintaining those endpoints won’t be wasted. And you’re betting that nothing more valuable could have been built with that same time.
Martin Fowler breaks the cost into three parts: the cost of building it, the cost of delaying other work, and the cost of carrying the extra complexity. All three work against you.
Build the one endpoint the current slice requires. Make it clean. Make it tested. Ship it. When the next slice needs another endpoint, build that one. Your API will end up shaped by real demand instead of speculation. And every endpoint in it will be there because someone actually needed it.
“It’s Useless If I Hardcode That Value”
In the image upload example, we hard-coded a known file path. It felt wrong. It felt like a shortcut that wouldn’t count.
It counted.
That hard-coded slice proved the entire pipeline worked end to end in two days. Server processing, asset creation, library reload, all connected and running. Every slice after that replaced one hard-coded piece with a real one. The file picker replaced the hard-coded path. Attribute editing replaced the defaults. Each replacement was small, tested, and shippable.
The hard-coded version isn’t the product. It’s the skeleton that proves the product can stand up. Once the skeleton is standing, you add muscle one layer at a time.
Without that skeleton, you’re two developers building from opposite ends for eight days, hoping everything connects at the end. With the skeleton in place, you have a working system on day two and a clear list of what to improve next.
That useless hard-coded slice is the most useful thing you can build. It eliminates integration risk on day one instead of deferring it.
“Who Would Even Want Such A Small Slice?”
Your product owner. Your teammates. Your users.
Every one of your stakeholders benefits from working in small slices. You validate assumptions. You will accelerate learning. You will unblock other work. And you’ll deliver real business outcomes sooner.
The Amazing Part
It’s not in any single example. It’s in the pattern that every example reveals, especially when you sit down afterward and rethink how the work could have gone.
The amazing part happens after the walking skeleton ships. It’s all the options that open up. It’s who benefits.
That first thin slice, the tracer bullet, puts every layer of the architecture into place. Once it’s standing, the work changes.
A product owner who saw zip code search working on day three could decide that the map wasn’t worth building at all, saving her team a week of work on something nobody needed.
Developers who rendered the shell of a 3D scene in week two could have started building screenshot, or tackled performance, instead of waiting three months to see anything on screen. Ninety minutes a day back in their lives. Fewer rewrites. Better software.
Brandon, who was about to spend eight days building from the database up, had a working pipeline in two. Every slice after that was a clear, small improvement instead of a leap of faith.
And that order processing team. Five people doing manual reviews while the system that would replace their work sat unfinished for three extra weeks. They could have had relief on day five. The sellers who poured weeks of effort into their products could have had buyers receiving them instantly, not sitting in a queue.
That gap still haunts me. Not the engineering. The engineering was fine.
What haunts me is the people. The time they spent waiting for value that could have arrived sooner. That’s the lesson that stuck: the cost of building from the inside out isn’t measured in code. It’s measured in the days that real people spend waiting for something better.
Slice thin. Ship early. Watch who benefits.
Deliver daily. One thin slice at a time.







