The 4 Types of Software Maintenance: Corrective, Adaptive, Perfective and Preventive

Learn the four types of software maintenance—corrective, adaptive, perfective and preventive—with practical examples and clear differences between each.

Imagine four items appearing in an application's maintenance backlog during the same week.

Checkout sometimes calculates the wrong discount. A forthcoming Android release deprecates an API the mobile app relies on. Users complain that generating a large report takes too long. Meanwhile, engineers have identified a fragile piece of payment code they want to restructure before the next major release.

All four involve changing software that is already in production. But they are being changed for different reasons.

That distinction is the basis of the four commonly used types of software maintenance:

  1. Corrective maintenance fixes faults that have already been discovered.
  2. Adaptive maintenance changes software so it continues working when its environment changes.
  3. Perfective maintenance improves the software's performance, usability, functionality or maintainability.
  4. Preventive maintenance addresses weaknesses before they become operational problems.

The categories are useful because “maintenance” covers a wide range of engineering work. Classifying a change by its purpose makes it easier to understand why the work is necessary, how urgent it is and what outcome the team expects.

The current ISO/IEC/IEEE 14764:2022 software maintenance standard establishes definitions and processes for software maintenance, while IEEE's overview of software maintenance uses the corrective, adaptive, perfective and preventive categories to distinguish the main reasons software is modified after delivery.

[Internal Link: “What Is Application Maintenance? A Complete Guide to Keeping Your App Healthy”]

The four types of software maintenance at a glance

The simplest way to distinguish them is to look at what triggered the change.

Type

Why the change happens

Simple example

Corrective

Something is already wrong

Fixing a checkout calculation bug

Adaptive

Something outside the app has changed

Updating an app for a new operating-system requirement

Perfective

The existing product could work better

Making a slow reporting workflow faster

Preventive

A weakness may cause trouble later

Refactoring fragile code before it begins causing failures

IEEE's software-maintenance overview makes another useful distinction: corrective and preventive maintenance are primarily corrections, while adaptive and perfective maintenance are enhancements to an existing system.

That does not mean every piece of work fits into a perfect box. Real maintenance tasks can overlap. The value of the categories is in identifying the main reason the change is being made.

1. Corrective maintenance: fixing something that is already wrong

Corrective maintenance is the easiest category to recognise.

A defect exists in the released application and needs to be corrected.

The problem may have been reported by a user, found during testing, detected through monitoring or discovered while investigating another incident. What matters is that the software is already behaving differently from how it is supposed to behave.

The IEEE description is straightforward: corrective maintenance deals with faults discovered after delivery, from urgent production fixes to defects that can wait for a scheduled release. IEEE: Software Maintenance

Examples include:

  • users being logged out unexpectedly;
  • an invoice calculating tax incorrectly;
  • an export producing incomplete data;
  • a mobile app crashing when a particular screen opens;
  • an API returning the wrong result for certain inputs;
  • an automated process occasionally failing to complete.

Corrective work can vary considerably in urgency. A typo in an administrative screen and a defect preventing customers from completing payment are both corrective maintenance, but they should clearly not be handled with the same priority.

Corrective maintenance does not always mean emergency maintenance

It is easy to equate corrective maintenance with firefighting, but a known defect does not always need an immediate hotfix.

Suppose an error affects an obscure administrative workflow used twice a year. The team may document the issue and include the correction in its next scheduled release.

The work is still corrective because its purpose is to repair a known fault.

An emergency production fix is simply one particularly urgent form of corrective work.

Corrective maintenance contributes most obviously to Levelworks' Error Free App Health Aspect, but it also depends heavily on the application being Observable and Explainable & Debuggable. Finding a bug is much easier when logs, monitoring and diagnostic information help engineers understand what actually went wrong.

2. Adaptive maintenance: keeping the app working as its environment changes

Adaptive maintenance is different because the application may not have anything wrong with it when the work begins.

Instead, something around it has changed.

The software has to adapt so it remains usable in a new or changing environment. IEEE gives examples such as operating-system upgrades, database migrations and external API changes.

Consider a mobile application that relies on an operating-system API. The code works correctly today, but the platform provider announces that the API is being deprecated and developers should move to a replacement.

Google's Android documentation provides real examples of this process. Android releases regularly deprecate older APIs when platform behaviour changes or newer alternatives become available, and developers are directed toward the replacement APIs. Android Developers: API Deprecations

Nothing necessarily “broke” inside the app.

The environment moved, so the application has to move with it.

Other examples of adaptive maintenance include:

  • changing an integration because a provider releases a new API version;
  • updating an application for a new browser behaviour;
  • adapting software to a newer database engine;
  • modifying authentication after an identity provider changes its requirements;
  • updating a mobile app for new operating-system restrictions;
  • changing software to meet an external regulatory or business-rule change.

The common thread is that the trigger comes from outside the existing application.

Adaptive maintenance is why old apps cannot simply remain untouched

Software often depends on technology whose lifecycle is controlled by somebody else.

Operating systems introduce new requirements, cloud providers retire services, APIs reach end-of-life and frameworks change their supported environments. An application that never adapts eventually becomes separated from the ecosystem it needs to operate in.

Within Levelworks' App Health framework, adaptive maintenance is closely connected to keeping an application Current & Updated, Compatible and Integrable.

The aim is not to chase every technology change. It is to respond to the external changes that materially affect the application's ability to continue doing its job.

[Internal Link: “Why Dependency Updates Are Essential to App Maintenance”]

3. Perfective maintenance: making a working application better

Perfective maintenance begins with software that already works, but could work better.

IEEE describes perfective maintenance as improvements beyond the original state of the product, including user-requested enhancements, documentation improvements and changes intended to improve efficiency or maintainability.

Suppose customers can already generate reports successfully, but reports containing several years of data take too long to produce. Optimising the underlying queries would be perfective maintenance: there is no defect preventing the report from working, but the application's performance can be improved.

Other examples include:

  • making an existing workflow easier to use;
  • speeding up a slow but functional search;
  • reducing unnecessary resource consumption;
  • improving the maintainability of an existing component;
  • adding validation that makes an existing feature easier to use;
  • refining an interface after observing how users actually interact with it.

Perfective maintenance often develops from what teams learn after release.

Software used by real people generates information that cannot always be obtained during development. Teams discover which workflows matter most, where users hesitate, which operations become slow with real data and which parts of the codebase are difficult to change.

Perfective maintenance uses that information to improve the existing product.

Where does perfective maintenance end and new development begin?

This boundary is not always precise.

Improving the speed of an existing reporting feature clearly fits perfective maintenance. Building an entirely new reporting platform probably looks more like product development.

A useful test is to ask whether the work is primarily improving or extending an existing capability or creating a substantially new product capability with its own requirements, architecture and development effort.

Contracts may draw the boundary differently, so organisations should not assume that every enhancement automatically belongs inside a maintenance agreement.

From an App Health perspective, perfective maintenance commonly strengthens qualities such as Performant, User Friendly & Delightful, Scalable and, where internal structure is improved, Explainable & Debuggable.

4. Preventive maintenance: fixing weaknesses before they become failures

Preventive maintenance is the least visible of the four categories because it often addresses a problem users have not experienced yet.

Engineers identify a weakness in the application and change it because leaving it alone increases the chance of future failure, security exposure or maintenance difficulty.

IEEE describes preventive maintenance as finding and correcting latent faults before they turn into operational faults.

Examples might include:

  • restructuring particularly fragile code;
  • removing an unsupported dependency before it causes compatibility problems;
  • strengthening tests around a risky component;
  • cleaning up error-prone configuration;
  • replacing a brittle manual process;
  • addressing a known security weakness before it is exploited;
  • simplifying code that has become increasingly difficult to modify safely.

Refactoring is a common example.

Martin Fowler defines refactoring as changing the internal structure of software so that it becomes easier to understand and cheaper to modify without changing its observable behaviour. Martin Fowler: Definition of Refactoring

That is often preventive maintenance in practice: users may see no difference after the release, yet the application becomes less likely to create problems during future changes.

Google's engineering guidance makes a similar point from a code-health perspective, warning that codebases can deteriorate through many small reductions in maintainability over time and encouraging changes that improve overall code health. Google Engineering Practices: The Standard of Code Review

Preventive maintenance is not speculative engineering

Preventive work can become wasteful if teams use it as an excuse to rewrite anything they dislike.

Good preventive maintenance should address a recognisable risk.

There should be a reason to believe the current condition could create future problems: repeated difficulty modifying a module, unsupported technology, poor testability, unsafe configuration, unreliable deployment steps or code that has already produced near-misses.

The goal is not to make every part of the application theoretically perfect.

It is to deal with weaknesses while they are still cheaper and safer to correct.

[Internal Link: “Preventive App Maintenance: How to Fix Problems Before Users Find Them”]

The same technical task can belong to different maintenance types

One of the most useful things to understand about these categories is that the task itself does not determine the category; the reason for doing it does.

Take a dependency update.

It could be corrective maintenance if the current dependency contains a defect that is already causing production failures.

It could be adaptive maintenance if the application needs a newer version because the operating system or another external platform has changed.

It could be perfective maintenance if the newer dependency materially improves the performance of an existing feature.

Or it could be preventive maintenance if the current version contains a known weakness that has not yet caused an operational problem.

Security patches provide another good example. NIST defines patch management as identifying, acquiring, installing and verifying changes that correct security or functionality problems. NIST: Patch Management

But “applying a patch” is not itself a fifth maintenance category. Depending on why the patch is needed, the work may be corrective, adaptive or preventive.

This is why maintenance tickets are more useful when they describe both the work and the reason for it.

Corrective vs adaptive vs perfective vs preventive: how to tell them apart

When the category is unclear, ask what triggered the work.

Something has already failed or behaves incorrectly

That points to corrective maintenance.

“The login flow occasionally returns an error and we need to fix it.”

Something outside the application has changed

That points to adaptive maintenance.

“Our authentication provider is retiring the API version we currently use.”

The application works, but we want it to work better

That points to perfective maintenance.

“The search works correctly, but response time is poor on large datasets.”

Nothing has failed yet, but we can see a credible future risk

That points to preventive maintenance.

“This module is becoming difficult to change safely, so we should restructure it before the next feature release.”

That decision model is often more useful than trying to classify work based on whether it involves a bug fix, refactor, upgrade or code change.

Reactive and proactive maintenance are not the same as the four types

There is some overlap, but these are different ways of describing maintenance.

Corrective maintenance is usually reactive because a defect has already been discovered.

Preventive maintenance is inherently proactive because it acts before an operational fault appears.

Adaptive maintenance often happens in response to an announced external change, but teams may have months to prepare for it. Perfective maintenance is generally planned because the application is already functioning.

The distinction matters because a maintenance programme made almost entirely of corrective work will feel very different from one that has enough capacity for adaptive, perfective and preventive improvements.

[Internal Link: “Reactive vs Proactive App Maintenance: Which Approach Costs Less?”]

How the four maintenance types relate to App Health

Levelworks' App Health Aspects offer another way to look at the outcome of these maintenance categories.

Maintenance type

App Health Aspects it commonly strengthens

Corrective

Error Free, Supported, Explainable & Debuggable

Adaptive

Current & Updated, Compatible, Integrable, Compliant

Perfective

Performant, User Friendly & Delightful, Scalable

Preventive

Resilient, Secure, Tested, Explainable & Debuggable

These relationships are not fixed. A single maintenance change can improve several aspects of application health.

The point is that the four maintenance types describe why work is being done, while App Health describes what condition the application should be kept in.

That distinction helps prevent maintenance from becoming an undifferentiated backlog of technical tasks.

A healthy maintenance programme needs more than one type

If nearly every maintenance ticket is corrective, the team is spending most of its time dealing with problems after they have appeared.

If the team only performs preventive work, meanwhile, it risks investing heavily in hypothetical future problems while ignoring real user needs.

Healthy software maintenance tends to require all four categories at different points in the application's life.

Corrective work restores expected behaviour when defects appear. Adaptive work keeps the software aligned with changes outside its control. Perfective work improves a product as teams learn more about how it is actually used. Preventive work deals with technical weaknesses before they become expensive failures.

The mix will change over time.

A newly launched application may generate more corrective work as real-world edge cases emerge, while a mature platform may need greater adaptive effort as frameworks, integrations and infrastructure age. A system preparing for significant growth may need perfective performance work alongside preventive improvements to fragile parts of the codebase.

There is no useful universal percentage for how much of each type a team should perform.

What matters is that the maintenance programme can distinguish between them and does not allow urgent corrective work to consume all available attention indefinitely.

The four types describe four different reasons software changes after launch

Corrective, adaptive, perfective and preventive maintenance are sometimes taught as four definitions to memorise. In practice, they are more useful as four questions:

What is already broken?

That is corrective maintenance.

What changed around the application?

That is adaptive maintenance.

What could work better?

That is perfective maintenance.

What weakness should we address before it causes trouble?

That is preventive maintenance.

Real maintenance work will not always fit perfectly into one category, and it does not need to. The purpose of the framework is to make the intent behind a change clearer.

For Levelworks, that intent ultimately comes back to App Health. Some changes restore health, some help the application adapt, some improve its current condition, and others protect it from risks that are beginning to develop.

Together, those four kinds of work are what allow an application to keep functioning without simply waiting for the next thing to break.

‍

Continue reading