Software Is Never Finished
Our longest-running project taught us the simplest and least comfortable lesson at once: requirements never stop changing. Software is never finished. The only answer is to keep change cheap. No heroics.
What is this? · Engineering Story
A lesson learned — a mistake, why it happened and what it taught us. Anonymized, no client named, no drama. The mistake is the teacher, not the hero. Go to overview
- Author
- Batunet Engineering
- Reading time
- 4 min
- Level
- Advanced
- Status
- Approved
On this page
Some lessons can only be learned over years, because they only reveal themselves over years. This is one of them. It is deliberately kept general — no client, no project, no point in time.
Situation
In our longest-running client project, a system served its purpose over a long period of time. Nothing about this story is dramatic: the system ran, it was needed, it kept being developed. The lesson lies precisely in that lack of spectacle — not in a single event, but in what the passage of time made visible.
Initial assumptions
At the outset, spoken or not, there is the idea of an end state: at some point the system will be finished, the requirements met, the work done. That idea shapes how you build — you align the system with the known need as precisely as possible. Getting finished looks like the goal.
Problem
Over the years, the end state turned out to be a fiction. The requirements never stopped changing — not because something had been planned wrong, but because the world the system lives in changes: new needs, new circumstances, new questions nobody knew about when it was built. A system built for a fixed end state becomes more brittle against this continuous change with every year. What once fit precisely later fits too tightly.
Root cause
The root cause was the assumption of an end state itself. If you believe a system will be finished, you optimize it for the needs known today and thereby make it rigid against the unknown needs of tomorrow. The mistake is not that requirements change — that is the normal case — but an architecture that pretends this normal case won't happen. The more precisely you build for today, the more expensive tomorrow becomes.
Decision
The lesson was to give up the end state as a goal and put a different one in its place: not a finished system, but a changeable one. The decisive question is no longer "is it finished?" but "how expensive is the next change?" — and the architecture is measured by that, not by how precisely it fits the current state.
Implementation
In practice, this means building the system so that change stays cheap: clear boundaries so a change stays local; little coupling so an intervention doesn't ripple out everywhere; the domain logic expressed in a way that can be adapted without touching everything. The yardstick is not a perfect fit for today but affordable adaptability for tomorrow. Over the long lifetime of the project, this paid off again and again — every requirement that came along cost less than it would have in a rigidly optimized system.
Trade-offs
Building for changeability means giving up part of the maximum fit to today's needs. A system that keeps every future change affordable is rarely the most elegant one for the single current case at that moment. That is the deliberate price. We would only decide differently for a system that is foreseeably short-lived — there, the investment in changeability is wasted, because the tomorrow you are preparing for never comes.
What we learned
Software is never finished because the world is never finished. Requirements change continuously, and that is not a defect but the condition under which software lives. The only robust answer is an architecture that makes change cheap — not one optimized toward an end state that never exists. The value of a long-lived system is not measured by how well it fits today, but by how little the next change costs.
How this changed Batunet
Since then, we don't promise a finished system but a changeable one — and we measure our work by how affordably the next requirement can be met. We treat continuous change as the normal case you build for, not as a disruption of a plan. That takes the menace out of "never finished": it is not a weakness of the project but the nature of the thing — and you can design for it.
Further reading
- Guide: Software that still runs in ten years — why changeability is the real yardstick over a system's lifetime.
- Guide: Why software projects really fail — why early, rigid commitment becomes expensive as understanding grows.
- Guide: Legacy modernization without a big bang — how to keep evolving a long-lived system over years.
- Decision: Modular monolith as the starting point — boundaries that keep changes local.
It is grounded in the Batunet Engineering Method: build for change, not for an end state — and make changeability the yardstick.
"Finished" is not a state software reaches, but an idea you have to let go of. What remains is the question of how much the next change costs.
Referenced entities
Continue your engineering journey.
Related concepts, decisions, playbooks and perspectives — as one connected path, not a list of links.
Concepts
Engineering decisions
A concrete project in this field?
Reference Guides show how we think. For your system, talk to our management — technical, no sales pitch.
