The launch of a custom software project is not the end of the project. It is the beginning of a different relationship with the system. Most clients understand this in theory; fewer plan for it in practice. The businesses that get the most out of custom software treat maintenance as a standard operational cost, not a line item to minimize.

I have watched this play out both ways enough times to have a strong opinion about it. The clients who budget for maintenance from day one end up with systems that keep getting better for years. The ones who treat launch as the finish line end up with a system that works fine until the day it does not, and by then the fix is expensive and urgent instead of routine and cheap.

What Maintenance Actually Involves

Maintenance on custom software is not just fixing bugs. It includes several distinct categories of ongoing work, and clients are often surprised by how much of it has nothing to do with anything going wrong:

  • Bug fixes. Every software system has bugs. The question is severity and frequency, both of which can be managed with good initial development practices and proactive monitoring. Critical bugs need fast response. Minor ones get batched.
  • Dependency updates. Custom software runs on a stack: a language runtime, a framework, libraries, database software, server software. All of these release updates, some of which are security patches that cannot wait. Staying current on dependencies is not optional over time.
  • Integration maintenance. The third-party tools your system connects to change their APIs. When they do, your integration may break. This is one of the more unpredictable maintenance costs, and the more integrations a system has, the more exposure there is.
  • Feature additions. As the business changes, the software needs to change with it. A booking system built when you had one service area will need modification when you expand to three. Planning for this kind of evolution is part of building a maintainable system in the first place.
  • Performance tuning. As usage grows, queries that were fast enough at launch may slow down. Index maintenance, query optimization, and infrastructure scaling are ongoing concerns for systems that handle real volume.

A concrete example from the dependency category: a payment processor deprecates an old API version and gives integrators a year’s notice. Most businesses do not track that notice at all — it goes to a developer’s inbox, or to no one, because the vendor relationship is with the software, not with a person watching for deprecation notices. If nobody is assigned to catch it, the year passes, the deprecation date arrives, and payments stop working with no warning to the business owner. That is not a hypothetical. It is the single most common cause of “the software just stopped working” calls I get from businesses that built something years ago and never set up an ongoing maintenance relationship.

Documentation and Knowledge Transfer

One of the most common maintenance problems I see is a system where the original developer is no longer available and no one documented how it works. The system runs, no one wants to touch it, and every change becomes an excavation.

Proper documentation is part of what I deliver at the end of a build. That includes architecture notes, integration documentation, deployment procedures, and enough context that a competent developer who did not build the system can maintain it. It also means the client is not permanently dependent on one developer.

I have inherited systems from other developers where the documentation consisted of a single README that said “run npm install and npm start.” No notes on why certain decisions were made, no record of which third-party services the system depended on, no explanation of a workaround that looked like a bug until I understood the reason it was there. Reverse-engineering a system like that before you can safely touch it can eat up more hours than a clean handoff would have cost to produce in the first place. Documentation is not busywork. It is the difference between a maintenance visit that takes an hour and one that takes a week.

Planning the Maintenance Budget

A reasonable starting point for custom software maintenance is 15-20% of the build cost per year. That number varies depending on integration complexity, how actively the system is being extended, and how often dependencies in the underlying stack require updates.

Some clients prefer a retainer that covers a set number of hours per month. Others handle maintenance reactively. The retainer model produces better outcomes because it keeps the relationship active, which means the developer has current context when something needs to change. Reactive maintenance on a system the developer last looked at two years ago is slower and more expensive.

There is also a psychological benefit to the retainer model that clients underestimate: when a small issue comes up, a client on a retainer mentions it right away because the relationship is already active and the cost is already accounted for. A client without a maintenance relationship tends to let small issues pile up because each one feels like it requires opening a new engagement, getting a new quote, and justifying the spend. By the time they call, three small issues have become one large one.

What Good Maintenance Looks Like in Practice

A maintained custom system should have monitoring in place that alerts on errors and performance degradation before users report problems. It should have a staging environment where updates can be tested before they go live. It should have backups that are tested, not just configured.

“Tested” is the operative word on backups. I have seen businesses discover, in the middle of an actual data loss event, that their nightly backup job had been silently failing for four months. A backup that nobody has ever restored from is a backup you cannot fully trust. Part of a good maintenance program includes periodically restoring a backup to a test environment just to confirm the process actually works end to end.

None of this is complicated, but it requires intentionality. A system that gets deployed and then forgotten until something breaks will accumulate technical debt that makes every future change harder and more expensive than it should be.

Who Should Own the Maintenance Relationship

Some businesses put an in-house employee in charge of maintenance oversight even when the actual development work is outsourced. That works well when the employee has enough technical literacy to have an informed conversation with the developer, review what is being proposed, and catch the difference between a genuinely necessary update and busywork being billed by the hour. It works poorly when the employee has no technical background and simply approves whatever is presented, because at that point there is no real oversight at all — just an extra layer between the business and the decision.

The businesses with the smoothest long-term relationships tend to be the ones where someone on the client side stays engaged enough to ask good questions, even if they are not writing any code themselves.

The Alternative

Some clients, after seeing what maintenance involves, decide they prefer a SaaS tool where someone else handles all of this. That is a legitimate choice, and I will tell you honestly if I think it is the right one for your situation. The maintenance burden of custom software is real, and it belongs in the decision about whether to build in the first place.

At Salterra, ongoing maintenance is a service I offer for systems I build, which means the documentation and handoff are designed with that in mind from the start.

The full picture of how I approach custom software projects is on the software development page. If you are earlier in the decision process, build vs buy is a useful framing for whether the ownership model of custom software is the right fit for your business.