Software is never finished. It is only abandoned, deprecated, or still in use. The concept of a ‘done’ state is borrowed from manufacturing, where a car rolls off the line and stops changing, and it has never belonged in software at all.

This isn’t pessimism. It’s the most clarifying thing you can accept about the work. Once you stop treating ‘done’ as a destination, you start building systems that account for continuous change rather than systems that pretend the change won’t come.

The Industrial Model Doesn’t Map

When Ford finishes a Mustang, it ships. The physical object leaves the factory and enters a world where changes to it require recalls, costly logistics, and significant friction. Software has none of that friction. A patch can reach every user simultaneously. An architectural change can be invisible to end users while being total underneath. The cost of changing shipped software approaches zero compared to shipped physical goods.

This is entirely the point. The marginal cost of software is zero, and so is the marginal cost of changing it. The industrial model of ‘done’ exists to account for the cost of physical change. Remove that cost, and the model collapses.

Software teams that internalize this ship faster, maintain less anxiety about releases, and build more honest roadmaps. Software teams that resist it spend enormous energy on pre-launch perfection rituals that mostly create delay without reducing post-launch work.

Every Spec Is a Snapshot of Incomplete Knowledge

When you write a requirements document, you are writing down what you believe users need based on what you understand about users today. The moment you write it, it starts going stale. Users don’t know what they want until they have something to react to. Markets shift. Competitive pressure surfaces requirements that didn’t exist six months ago.

This isn’t a failure of product management. It’s an epistemic problem that no process can fully solve. The Agile movement understood this and built iteration into the methodology itself, though many teams adopted the ceremonies without absorbing the underlying insight: you cannot specify your way to done because the specification is always an approximation of a moving target.

The practical consequence is that a feature declared ‘done’ in sprint review is better understood as ‘done enough to learn from.’ That’s not a semantic trick. It changes what you measure, what you expect from users, and how you budget the next sprint.

Diagram contrasting a single completion point that drops off versus a continuous improvement timeline
The 'done' model versus the maintenance model. One of these accurately describes how software actually behaves in production.

Maintenance Is Not a Failure State

There’s a persistent and damaging attitude in engineering culture that maintenance work is lesser work, that you’re paying down someone else’s debt rather than building something real. This attitude is why critical open-source infrastructure runs on unpaid volunteer labor and periodic panic. Open source software runs the world, and almost no one is paid to maintain it.

But the same dynamic plays out inside companies. Teams celebrate launches and neglect the systems that quietly keep working. The software that’s been in production for five years accumulates dependencies that drift, security vulnerabilities that compound, and performance characteristics that degrade against changing load patterns. None of this is visible until it fails.

Declaring software ‘done’ is often how this neglect gets institutionalized. The project gets launched, headcount moves to the next thing, and the system enters a kind of undead state: officially complete, actually decaying.

The honest alternative is to treat maintenance as part of the normal cost of ownership from day one, budget for it explicitly, and resist the impulse to declare victory and move on.

Good Enough Is a Real Answer, Just Not a Final One

None of this means software should never ship, or that ‘done enough’ is a surrender. Shipping matters. A system that works adequately and reaches users is worth infinitely more than a system still in development. The goal of shipping hasn’t changed. What needs to change is the framing around what comes after.

The right mental model is closer to infrastructure than to manufacturing. A road is never ‘done.’ It’s resurfaced, widened, rerouted, and replaced on timelines that reflect use and decay. Nobody finds this surprising. Software should work the same way, and teams that build with that expectation write more maintainable code, plan more realistic timelines, and have healthier relationships with their own technical debt.

The Counterargument

The reasonable objection is practical: organizations need closure. Budgets get allocated and closed. Teams need to move on. Contracts specify deliverables. All of this is true, and none of it requires that we pretend software is actually done.

You can close a budget cycle without declaring the software finished. You can ship a version, hand off ownership, and define success criteria without the fiction that no further work will be required. The problem isn’t that organizations need structure. It’s that ‘done’ is a lazy shorthand for ‘we’ve met the current criteria,’ and the laziness causes real downstream harm when teams use it to stop paying attention.

Define what you’re shipping, what success looks like in the next 90 days, and who owns it afterward. That’s a complete answer. It doesn’t require calling anything finished.

Stop Waiting for Done

Software is a process, not a product. The artifact you ship is evidence of where the process was at a particular moment. Treating that moment as terminal makes you worse at the work: worse at planning, worse at maintenance, worse at understanding what users actually need over time.

Ship early. Ship often. Define your current criteria clearly. Assign real ownership for what comes after launch. And drop the word ‘done’ from your vocabulary except to mean ‘done for now, pending what we learn next.’ That’s not a lower standard. It’s a more honest one.