Back to insights

The Maintenance Bill Nobody Quotes: What It Actually Costs to Keep Software Running

Roy LevyRoy LevySeptember 202613 min readProduct & delivery
Launch closes the build invoice. It opens a second one that nobody quoted.

The build quote had a number on it. Design, development, testing, launch. You budgeted for it, you paid it, the product went live, and the invoice closed.

Nine months later you're getting emails you don't fully understand. A payment provider is deprecating the API version you're on. A dependency has a security advisory with a CVE number attached. The hosting bill has quietly doubled. Something broke on a Sunday and there was nobody to call, so it stayed broken until Monday.

None of that was on the quote. All of it was always going to happen.

Software isn't a building you take delivery of. It's closer to a boat: it's in the water, and the water is doing things to it whether or not anyone is aboard. The build cost buys you the boat. It doesn't buy you the next five years of being in the water.

This is the most consistently under-planned line in a founder's budget, and unlike most budgeting mistakes, this one gets more expensive the longer you ignore it.

Four clocks that run whether or not you touch the code

The thing that surprises founders most is that a product decays while nobody is changing it. You can ship, walk away, change nothing, and still have a broken system in eighteen months. That's not neglect. It's four independent clocks, none of which you control.

The runtime clock. Every language runtime has a published end-of-life schedule. Node 20 — the default LTS for anything built through most of 2024 — went end of life on 30 April 2026. If your app was built in that window and nobody has touched the runtime since, it has been running without security patches for months. Node 22 goes end of life in April 2027. Node 24 in April 2028. These dates are known years in advance and arrive regardless of how your business is doing.

The dependency clock. A modest Next.js app pulls in hundreds of transitive packages. Some of them will publish a security advisory this year. Some will publish a breaking major. A few will be abandoned. You didn't choose most of them individually, but you inherit all of their calendars.

The vendor clock. Stripe deprecates API versions. OAuth providers tighten scopes. Apple and Google change store review policy. If you're on a platform — Wix, Shopify, Salesforce — the platform ships breaking changes on its own schedule and gives you a window to comply. Miss the window and your app stops working or stops being listed.

The data clock. The query that returned in 40ms against 8,000 rows behaves differently at 800,000. Nothing in your code changed. The shape of your data did. This one is the sneakiest because it degrades gradually and gets blamed on "the app feeling slow lately."

Three of those four clocks tick even if you never ship another feature. That's the part that isn't intuitive, and it's why "we're not planning any changes next year" is not a maintenance plan.

Not every product has the same bill

Before the numbers, the honest caveat — because the opposite mistake is real and I see it charged for.

A static marketing site on managed hosting, no login, no payments, content in a CMS, genuinely needs close to nothing. Maybe a few hours twice a year. If someone is selling you a monthly retainer for that, ask them what they'll be doing in the months where nothing happens. There isn't always a good answer.

Roughly three tiers, and it's worth knowing which one you're in before you agree to anything:

  • Content sites. Marketing pages, blog, forms. Little state, no money moving, few integrations. Low bill, and honestly low risk if you skip a quarter.
  • Real applications. Accounts, permissions, payments, a database that matters, two or three integrations. This is where most funded early products live, and where the bill starts being a real line item.
  • Platforms. Multi-tenant, background jobs, third-party APIs you don't control, customers whose own work stops when you're down. Here maintenance stops being maintenance and becomes operations.

Most of what follows is aimed at the middle tier, because that's where the gap between what founders budget and what things cost is widest.

What the bill is actually made of

When a founder hears "maintenance" they usually picture hosting. Hosting is the smallest and most predictable piece. Here's the rest of it.

The bill

Hosting is the line everyone budgets.

The rest is the one nobody quotes.

  • 01

    Infrastructure

    Predictable, and the smallest piece

  • 02

    Staying current

    Work nobody can put in an investor update

  • 03

    Things breaking

    Scales with users, not features

  • 04

    Small changes

    Two hours or two days, depending on structure

  • 05

    Availability

    Response time is the product

1. Infrastructure

Hosting, database, storage, email delivery, error tracking, whatever else has a monthly invoice. For a small application this is typically somewhere between $100 and $500 a month, and it scales with usage in ways that are mostly reasonable.

This is the line everyone budgets and almost nobody gets badly wrong. Skip ahead.

2. Staying current

Runtime upgrades, framework majors, dependency updates, vendor API migrations. Work that produces nothing a user can see and nothing you can put in an investor update.

This is the line nobody budgets. For a typical small application, plan on four to eight developer-days a year — assuming you're doing it continuously. That number is not a constant. It's what the work costs while it's still small.

3. Things breaking

Bugs found in production, integrations that start failing, a background job that silently stopped running in March. This scales with users rather than with features, which catches people out: the same codebase costs more to run at 2,000 customers than at 50, without a single line changing.

4. Small changes that aren't features

A tax rate changes. A price tier needs adjusting. Legal wants a line added to the footer. Support needs a field visible in the admin view.

Individually trivial. The thing that determines whether they cost two hours or two days is entirely how the codebase was put together. If the same business rule lives in five places — the standard outcome of both time pressure and generated code — then a "small change" means finding all five and being certain you found all five. That's the mechanism I've written about in The MVP Trap, arriving here as a monthly cost rather than a one-time one.

5. Availability

This is the expensive one, and it's the one that's hardest to see on an invoice because it isn't work at all.

The cost of fixing a broken checkout on a Saturday is maybe three hours. The cost of someone being available to fix a broken checkout on a Saturday is a different thing entirely, and it's most of what you're actually paying for in any support arrangement. Response time is the product. The repair is incidental.

Founders routinely negotiate hard on the hourly rate and then agree to a four-hour response guarantee without noticing they just bought the expensive part.

Realistic numbers

The industry heuristic is 15–25% of the original build cost per year. It's crude, but it's the right order of magnitude and it's a better planning assumption than the zero most people use.

I prefer thinking in developer-days, because it survives currency, region, and rate differences. Assuming continuous maintenance rather than deferred:

Content site. $0–50/month infra. Two to four developer-days a year. Call it a rounding error, and treat anyone quoting more than that as needing to justify it.

Small application — auth, payments, a database, a couple of integrations, a few hundred users. $100–500/month infra. Ten to twenty developer-days a year across all five categories above, weighted toward staying current and small changes. Against a $60–100k build, that lands roughly where the 15–20% heuristic predicts.

Platform. $500–3,000+/month infra. Thirty to sixty developer-days a year, plus somebody who is effectively on call. At this point you're deciding between a retainer and a part-time in-house engineer, and the honest answer is often the second one.

Two assumptions worth stating plainly: these are for a codebase in reasonable shape, and they assume the work happens as it arrives. Both of those assumptions fail often, and when they fail the numbers don't drift upward — they jump.

The only bill that grows when you don't pay it

Here's the part that makes maintenance different from every other operating cost.

Skip a month of hosting and you owe one month of hosting. Skip three years of upgrades and you don't owe three years of upgrades. You owe a migration project.

The reason is that upgrades compound against each other. Moving one framework major with current dependencies is a contained task with a changelog and a clear path. Moving three majors at once, on a runtime that's already end-of-life, with a dependency tree where four packages have their own breaking changes waiting, is not three times the work. Every incompatibility multiplies against every other one, and you can't stage it, because the versions you'd stage through are themselves unsupported.

Deferred maintenance also has a nasty second-order effect: it silently narrows your hiring pool and your options. A stack two years past its support window is harder to hire for, harder to get help with, and increasingly excluded from things you might want — a security review, an enterprise customer's vendor questionnaire, a SOC 2 process, an acquisition diligence checklist.

And the failure mode isn't gradual. It's a phone call. A vendor cuts off an old API version, or a CVE lands on something in your critical path, and now the migration you deferred for two years has to happen this week, on someone else's timeline, at whatever it costs.

I've made the case for refactoring over rewriting before, and this is the mechanism that pushes people toward rewrites they shouldn't be doing: not that the code is bad, but that it's now so far behind that starting over genuinely looks competitive.

What makes the bill smaller

Most of what determines your ongoing cost was decided during the build, before you had any way to evaluate it. A few things move the number materially:

Fewer moving parts. Every service, queue, and self-hosted component is a thing with its own upgrade path and its own failure mode. The most over-engineered systems aren't just slower to build — they're permanently more expensive to own.

Managed over self-hosted. Paying a vendor $40/month to run your database is almost always cheaper than a developer-day a quarter, and the developer-day is the real price of running it yourself.

Fewer integrations. Each third-party API is a clock you don't control. Sometimes worth it. Rarely free, and never free forever — which is the part missing from most build vs. buy reasoning.

Boring, current versions. Not the newest thing. The thing with the longest remaining support window and the most people using it.

One home per business rule. Directly determines whether small changes are cheap or dangerous. This is the single highest-leverage structural property of a codebase and it's invisible from the outside.

Automated dependency updates, reviewed by a human. Bots open the PRs, a person merges them. Cheap to set up, and it converts a recurring migration into background noise.

A written record of decisions. The cost of maintenance is mostly the cost of re-understanding a system. Nothing lowers that faster than a short decision log, and nothing raises it faster than the original developer being unreachable.

Five questions to ask before you sign a build contract

You don't need to read code to price this. Ask these while you still have leverage, which is before you've paid anything.

"What runtime and framework versions is this on, and when do they go end of life?" Not a trick question. Anyone competent knows the answer in five seconds. Hesitation is the finding.

"What's the monthly infrastructure cost at ten times today's usage?" You're checking whether anyone has thought about cost as a design input at all.

"What has to happen in the twelve months after launch even if we build nothing new?" If the answer is "nothing," they either haven't thought about it or they're telling you what you want to hear.

"If something breaks on a Saturday, what exactly am I entitled to, and what does that cost?" Get this in writing at contract time. Negotiated during an outage, it costs more.

"If you're unavailable for a month, who can deploy this, and do they already have access?" Access, not knowledge. Domains, DNS, cloud accounts, repository, app store, payment provider. If any of those are in one person's personal account, you don't fully own your product yet.

The last one has nothing to do with code quality and is the one I'd ask first if I could only ask one.

Three honest ways to structure it

On-demand, with scheduled windows. No monthly fee. Two or three planned blocks a year for upgrades and dependency work, plus an agreed rate and response expectation for anything urgent. For most small applications this is the right answer, and it's the one that gets recommended least often because it bills the least.

A retainer. Justified when you genuinely need guaranteed availability — real users, revenue that stops when you're down, or a pace of change that keeps someone occupied. Make sure it specifies response time and what happens to unused hours. A retainer that buys a vague sense of coverage and no defined obligation is the worst version of this.

In-house. Once you're at platform scale, or once maintenance plus feature work is consistently more than half a person's time, hiring is cheaper and the context stays in the building. If you're getting close, you're better off hiring properly than stretching a contractor arrangement past the point where it makes sense.

The wrong version of all three is the same: no arrangement at all, and a scramble every time a clock runs out.

The reframe

The build quote is the price of getting to the starting line. It is not the price of the product.

That isn't a reason to spend less on the build — usually the opposite, since most of what makes a product cheap to own is decided during the build by people the founder is trusting to have thought about it. It's a reason to ask what the ongoing number looks like before you're committed, and to treat it as a real line rather than an unpleasant surprise you'll deal with later.

The founders who get burned here are almost never the ones who spent too much building. They're the ones who assumed launch was the end of the spending.

If your app is already behind

If you're running on a version that's past support, or you haven't touched the dependencies since launch, or you're not sure who has access to what — that's an ordinary situation and a fixable one. It's cheaper to fix now than after a vendor sets the deadline for you.

That's a large part of what I do: taking over products that shipped, ran for a while, and quietly fell behind.

See how I approach full-stack product development

Questions about something you read here, or a project you want to move forward? I work with teams on full-stack builds, AWS and serverless consolidation, migrations, and messy systems.

Contact me