What Factors Affect the Cost of Maintaining an Application?

Two applications can have similar numbers of users, screens and features yet cost very different amounts to maintain.

In one, a developer can understand a change, update the code, run reliable automated tests and release it through a repeatable deployment pipeline in a few hours.

In the other, the same-sized request requires tracing dependencies across several tightly coupled modules, asking a long-serving engineer why the code behaves the way it does, testing manually, coordinating a production release and then watching closely because rollback is difficult.

The visible feature might be equally small.

The maintenance effort is not.

That is why estimating application maintenance as a simple percentage of original development cost is often misleading. Original build cost says little about how maintainable the software is today, how frequently its environment changes, how much production support it needs or how much effort is required to make a safe modification.

A more useful way to think about maintenance cost is:

Maintenance cost is driven by how much work the application generates and how much effort is required to understand, change, verify, release and operate it safely.

For Levelworks, this is closely connected to App Health. An application that is Well Documented, Tested, Observable, Current & Updated, Version Controlled and Seamlessly Updatable is generally easier to maintain because routine work requires less investigation, manual verification and operational effort.

Those qualities do not make maintenance free. They make maintenance more predictable.

First, be clear about what you are calling maintenance cost

Companies often combine several different expenses under “app maintenance.”

These may include:

  • engineering maintenance;
  • production support;
  • cloud infrastructure;
  • third-party software licenses;
  • monitoring platforms;
  • security tools;
  • vendor support contracts;
  • planned upgrades.

These costs are related, but they behave differently.

If cloud traffic doubles, infrastructure spending may rise without engineering maintenance effort increasing significantly.

Conversely, an application with very few users can still be expensive to maintain if every code change requires extensive manual testing and specialist knowledge.

For this article, the main focus is the technical effort required to keep an application working reliably over time. Infrastructure and vendor costs matter where the architecture or operating model causes them to create additional maintenance work.

1. Application complexity

Complexity is one of the strongest cost drivers, but it should not be confused with application size.

A large, well-separated application can sometimes be easier to change than a smaller application where every component depends on everything else.

Maintenance becomes more expensive when a developer needs to understand a large portion of the system before safely changing one part.

Common complexity drivers include:

  • tightly coupled modules;
  • many services with unclear boundaries;
  • shared databases used by unrelated functionality;
  • complex asynchronous workflows;
  • numerous runtime configurations;
  • multiple deployment environments;
  • duplicated business logic.

Imagine changing the way a customer's status is calculated.

In a cleanly separated system, one service may own that rule.

In a tightly coupled system, the status might also influence billing, reporting, permissions, email notifications and several database procedures.

The amount of code changed may remain small, but the blast radius that must be understood and tested becomes much larger.

DORA's research on loosely coupled teams and architecture highlights this relationship. Systems that allow teams to test, deploy and change components independently reduce coordination overhead, while tightly coupled architectures make relatively small changes dependent on wider parts of the organization and system.

More components do not automatically mean higher maintenance cost.

More coupling between components usually does.

2. Technical debt

Technical debt increases the cost of otherwise ordinary changes.

It may take the form of:

  • duplicated logic;
  • difficult-to-understand code;
  • temporary fixes that became permanent;
  • outdated architecture;
  • fragile modules;
  • inconsistent patterns;
  • abandoned migrations.

Technical debt is expensive because future work has to navigate around it.

Suppose adding one reporting field should require modifying one query and one API response.

If reporting logic has been duplicated across six modules over several years, the same change now requires locating every implementation, understanding subtle differences and testing all of them.

The feature has not become more valuable.

The cost of changing it has increased because previous design decisions made the system harder to work with.

Technical debt can therefore compound. A difficult area is avoided because it is expensive to change; more workarounds accumulate around it, making the next change even harder.

[Internal Link: “How Technical Debt Affects the Health of Your Application”]

The useful maintenance-cost question is not simply, “How much technical debt do we have?”

It is:

How much additional effort does the current structure add to normal maintenance work?

That makes debt measurable through the friction it creates.

3. Test coverage and test automation

Every maintenance change needs some level of verification.

The cost depends heavily on how that verification is performed.

Consider a small bug fix affecting checkout.

Team A changes the code and runs automated unit, integration and end-to-end tests covering the affected workflow. Human testing concentrates on the areas where judgment adds value.

Team B has almost no automated regression coverage, so somebody must manually test login, product selection, checkout, payment and order creation before the release can be considered safe.

Repeat that difference across dozens of maintenance changes each year and the cost becomes significant.

DORA's research on test automation notes that manual regression testing is time-consuming and expensive, while delayed feedback also increases the effort required to diagnose and correct defects.

Weak test coverage creates another cost: fear of change.

Engineers compensate for uncertainty with:

  • more manual testing;
  • longer release cycles;
  • wider coordination;
  • larger contingency buffers.

For Levelworks, this is the practical cost impact of Tested App Health. Testing is not simply a quality control expense; reliable automated feedback reduces the amount of work needed to make routine maintenance safe.

4. Documentation and knowledge concentration

A maintenance engineer spends time in two broad ways:

  1. changing the application;
  2. figuring out what needs changing.

Poor documentation increases the second.

If architecture, deployment, integrations and important historical decisions are not documented, maintainers have to recover that context from:

  • source code;
  • old tickets;
  • chat history;
  • production configuration;
  • other developers.

DORA's research on documentation quality found a strong relationship between high-quality internal documentation and organizational performance, and identifies clarity, findability and reliability as important documentation characteristics.

The cost becomes especially visible when knowledge is concentrated in a few individuals.

If one engineer is the only person who understands billing, every billing-related maintenance task depends on that person's availability.

Good documentation cannot replace technical expertise, but it reduces the amount of specialist time required to reconstruct routine context.

[Internal Link: “Why Good Documentation Makes an App Cheaper to Maintain”]

5. Age and support status of the technology stack

Application age by itself does not determine maintenance cost.

An older application running on well-supported technology can be straightforward to maintain.

The expensive situation is usually distance from currently supported versions.

Maintenance effort increases when the application relies on:

  • unsupported runtimes;
  • old frameworks;
  • outdated databases;
  • abandoned libraries;
  • obsolete build tools.

OWASP recommends maintaining an ongoing inventory of frameworks, runtimes, libraries and other components and monitoring them for vulnerabilities and support status. Its guidance on vulnerable and outdated components explicitly includes operating systems, servers, databases, APIs, runtimes and libraries.

Falling several major versions behind creates a different maintenance problem from performing smaller regular updates.

GitHub's Dependabot documentation illustrates one reason: in deep dependency graphs, updating a single vulnerable package may become impossible without also upgrading parent or related dependencies. GitHub therefore recommends staying relatively current because that increases the likelihood that future security fixes can be applied without resolving a large chain of incompatibilities. GitHub: Dependabot dependency update errors

Postponed upgrades do not eliminate maintenance cost.

They often concentrate it into a larger future event.

6. Number and criticality of third-party integrations

Each important external integration adds another relationship the application team must maintain.

That can include:

  • payments;
  • identity;
  • CRM;
  • email;
  • maps;
  • shipping;
  • analytics;
  • accounting;
  • external data providers.

The maintenance cost does not come simply from the number of API calls.

It comes from external change.

Providers can alter:

  • API versions;
  • authentication;
  • SDKs;
  • quotas;
  • webhook behavior;
  • pricing plans.

A ten-integration application where most connections are stable and loosely coupled may be relatively inexpensive.

A five-integration application can be costly if all five are business-critical and change frequently.

Integration cost also rises when external behavior is spread directly throughout the application rather than isolated behind clear interfaces.

[Internal Link: “Why Third-Party Integrations Fail Over Time”]

A useful cost assessment therefore records not only how many integrations exist, but their criticality, volatility and degree of coupling to the core application.

7. Observability and diagnostic difficulty

When production problems occur, somebody has to determine what happened.

Good observability reduces the amount of engineering time spent doing that.

Poor observability turns diagnosis into reconstruction.

An application with useful:

  • structured logs;
  • metrics;
  • traces;
  • error reporting;
  • correlation IDs;
  • dashboards;

may allow an engineer to move quickly from a user report to the failing component.

Without them, the team may need to reproduce the issue manually, search several systems and add temporary logging before even beginning the fix.

AWS's Well-Architected guidance recommends using observability telemetry to make informed operational decisions and take prompt action when outcomes are at risk. AWS Well-Architected: Operational Excellence

This is why Observable and Explainable & Debuggable App Health have economic consequences.

They shorten investigation.

And investigation time is part of maintenance cost.

8. Release and deployment effort

A maintenance fix is not finished when the code is written.

It has to reach production.

Compare two release processes.

Application A

A pull request triggers automated tests, creates a build artifact, deploys through CI/CD and runs post-deployment validation.

Application B

An engineer builds locally, uploads files manually, changes production configuration, runs a database script and verifies the release from a checklist.

Even if the application change takes the same engineering time, Application B makes every maintenance release more expensive.

AWS recommends automating integration, testing and deployment specifically because doing so reduces errors from manual processes and reduces the effort required to deliver changes. AWS Well-Architected: Fully automate integration and deployment

Release friction is therefore a multiplier.

If your app needs one release a year, a cumbersome process may be tolerable.

If it needs fifty maintenance releases, the same process becomes a major recurring expense.

9. Manual operational work

Some applications continuously create maintenance work even when engineers are not changing code.

Teams may repeatedly:

  • restart services;
  • clear queues;
  • correct data manually;
  • provision environments;
  • rotate configuration;
  • investigate noisy alerts;
  • run repetitive scripts.

Google SRE calls repetitive, manual, operational work that provides little enduring value toil. Its Eliminating Toil guidance emphasizes an important characteristic: this type of work often grows as the service grows.

That makes manual operational work especially dangerous economically.

If every 1,000 new customers create ten more hours of manual work, maintenance staffing eventually has to grow with the customer base.

Automation changes that relationship.

AWS similarly recommends quantifying the time spent on operational work and prioritizing repetitive, time-consuming or error-prone activities for automation. AWS Well-Architected: Perform automation for operations

The important cost metric is therefore not merely how many operational tasks exist, but how much human attention they consume repeatedly.

10. Reliability and defect history

An application with recurring production problems naturally generates more maintenance work.

That includes both the engineering time required to fix defects and the operational cost surrounding them:

  • triage;
  • diagnosis;
  • support communication;
  • rollback;
  • recovery;
  • follow-up work.

A useful predictor of future maintenance burden is therefore the application's recent defect and incident history.

Look at:

  • recurring defect categories;
  • production incident frequency;
  • reopened bugs;
  • emergency releases;
  • repeat support issues.

A system that repeatedly fails in the same areas probably has structural maintenance work waiting behind the visible incidents.

Simply budgeting for faster responses does not remove that cost driver.

Correcting the recurring source does.

11. Security and compliance requirements

A low-risk internal tool and a regulated financial or healthcare application can require very different maintenance effort even if their codebases are similar in size.

Higher-assurance applications may require more:

  • security review;
  • patch tracking;
  • vulnerability remediation;
  • audit evidence;
  • access-control review;
  • change records;
  • compliance testing.

NIST's Secure Software Development Framework recommends integrating secure development practices throughout the software lifecycle so vulnerabilities are identified, mitigated and prevented from recurring.

That work requires engineering capacity.

The mistake is treating security and compliance obligations as exceptional costs that appear only during an audit. For applications where those requirements are permanent, they belong in the normal maintenance model.

12. Business criticality and support expectations

Two technically identical applications can have different maintenance costs because the business expects different levels of service.

An internal application used during office hours might reasonably operate with business-hours support.

A payment platform used globally may require:

  • 24/7 monitoring;
  • on-call engineering;
  • faster incident response;
  • stricter change controls;
  • greater redundancy;
  • more release validation.

Those requirements change staffing and operational effort even if the underlying code remains unchanged.

This is why maintenance cost cannot be estimated purely from technical architecture.

The required service level matters.

A system that must recover quickly from failures costs more to support than one where several hours of downtime are acceptable.

13. Frequency of change

Maintenance cost also depends on how often the application needs to change.

Consider two stable, well-built systems.

Application A receives one significant update per quarter.

Application B operates in an environment where dependencies, business rules, integrations and customer requirements change every week.

Application B will naturally require more engineering capacity.

Change can come from:

  • customers;
  • regulations;
  • operating systems;
  • browsers;
  • vendors;
  • security findings;
  • business processes.

The useful question is not merely “How old is the app?”

It is:

How much change does this application need to absorb each year?

A mature application in a stable environment can sometimes be inexpensive to maintain. A young application operating in a rapidly changing ecosystem may require substantial ongoing work.

The cost drivers interact

These factors rarely operate independently.

An outdated framework is more expensive to upgrade when automated tests are weak.

Complex architecture costs more when documentation is poor.

Third-party integration failures take longer to diagnose when observability is missing.

Frequent releases become expensive when deployment is manual.

This interaction explains why simplistic formulas based on application size produce unreliable estimates.

A more useful assessment looks at several dimensions together:

Cost driver

Lower-cost condition

Higher-cost condition

Architecture

Clear boundaries

Heavy coupling

Technical debt

Controlled

Accumulated

Testing

Reliable automation

Manual regression

Documentation

Current and findable

Tribal knowledge

Technology

Supported/current

Several versions behind

Integrations

Few/stable

Many critical/volatile

Observability

Fast diagnosis

Production blind spots

Deployment

Automated/repeatable

Manual/high-risk

Operations

Low toil

Frequent manual intervention

Reliability

Few recurring issues

Repeated incidents

Assurance

Standard

High security/compliance burden

Support

Business hours

High-availability / 24×7

Change rate

Stable

Frequent external/product change

A maintenance estimate should explain its assumptions

When evaluating maintenance cost, the most useful estimate is not simply:

“This application requires X hours per month.”

It should explain why.

For example:

  • expected level of support demand;
  • current technical health;
  • upcoming upgrades;
  • number of critical integrations;
  • release frequency;
  • required service coverage;
  • planned preventive work;
  • known modernization risks.

Those assumptions make the estimate adjustable.

If incident volume drops after fixing recurring defects, future effort can change. If the business adds 24/7 coverage or several critical integrations, required capacity may increase.

This is considerably more useful than relying on a generic percentage of original development cost.

Healthy applications are cheaper to change

The strongest long-term cost reductions usually do not come from negotiating a lower hourly engineering rate.

They come from reducing the amount of engineering effort required for each maintenance outcome.

Reliable tests mean less manual regression.

Good documentation means less rediscovery.

Observability shortens diagnosis.

Current dependencies keep routine upgrades manageable.

Automation removes recurring operational work.

Looser architecture reduces the number of components and teams affected by a change.

That is where Levelworks' App Health framework becomes economically useful. Well Documented, Tested, Observable, Current & Updated, Version Controlled and Seamlessly Updatable are not simply markers of engineering quality. They influence how expensive the next fix, upgrade or production investigation is likely to be.

[Internal Link: “How to Create an Annual App Maintenance Budget”]

A maintenance budget becomes much more useful once these underlying cost drivers are understood.

Because ultimately, the expensive application is not necessarily the largest one.

It is the one that makes the team work hardest to understand it, change it safely and keep it running.

‍

Continue Reading