Spec the foundations, then iterate the rest
The biggest risk in custom software was never going over budget. It was building the wrong thing - exactly to spec, on time, and useless. My bachelor thesis was on why digital projects fail, and the answer kept coming back the same: the spec wasn't good enough up front, so a team spent months building something the business didn't actually need. The fix, for years, was to spec harder - more detail, more sign-off, before any code.
Two things changed that. We learned which parts of a spec actually carry the risk, and the cost of changing software dropped. So we don't try to spec everything up front anymore. We spec the part that touches everything, and build the rest feature by feature.
Spec the foundations - the load-bearing parts
A few things in any tool aren't features in their own right. They sit underneath all the others: sign-in and authentication, permissions and access levels, the activity log that records who did what. Change one of these late and the change ripples out through every screen that depends on it, which makes them slow and expensive to retrofit.
These are the foundations, and they're worth defining properly before anything is built on top of them. This is where a clear, deliberate spec still earns its keep. Get the load-bearing parts right once, and everything you build afterwards rests on solid ground.
Then ship the features one by one
Once the foundations are set, individual features mostly stand on their own. They have dependencies between each other, but a change to one rarely reaches across the whole system - so there's no need to pin them all down in advance. You build one, put it in front of the people who'll use it, watch what happens, and adjust. Then the next. Direction gets confirmed while it's still cheap to change, and the tool grows to fit how the team actually works.
Why this works now: the cost of change dropped
The old logic for heavy specs was sound when it was written. Changing software late was slow and expensive, so you tried to decide everything before a line of code existed - and when you got a detail wrong, the whole project paid for it.
AI changed the economics. Making a change to a feature is now fast and cheap. When changing direction costs little, locking every detail up front buys you less and costs you more. So the spec gets shorter and sharper: you still nail the foundations, because those are still expensive to move, but you stop trying to predict every field and button - because those aren't.
This is how you avoid building what nobody uses
The most expensive software isn't the project that runs over. It's the one that ships exactly to spec, on budget, and then sits unused because the spec was wrong.
Fast feedback is the only real defence against that. Shipping features one at a time catches the mismatch between what was asked for and what's actually needed early - while a feature cost a day, not a quarter. That's the failure my thesis was about, fixed not by specifying harder, but by finding out sooner.
What stays fixed
Iterative doesn't mean open-ended. The price and the deadline are fixed up front, and so are the foundations - what flexes is the detail of the features built within them. You decide changes as you go, but you're never surprised by the bill, and the work doesn't drift forever. You get the adaptability of building as you learn, with the certainty of a number you agreed at the start.
That combination - solid foundations, flexible features, fast feedback - is what lets a custom tool end up fitting your business instead of fitting a document. Start a project and the first thing we'll do is pin down the foundations, then get a working feature in front of you, fast.