Forum Diskusi dan Komunitas Online

Full Version: Who Owns the Upgrade Clock in .NET Custom Software Development?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
A logistics company commissioned a customer portal and an internal operations app from a development partner in 2024. Both applications run on .NET 8. The contract covered the initial build along with a monthly retainer for enhancements and bug fixes.

In mid-2026, the company's security team noticed that .NET 8 support would end in November. It asked the development partner for an upgrade plan. The partner responded that runtime upgrades were outside the original scope and provided a separate project quote covering third-party library updates, testing, and deployment changes.

The company now has four months, no budget allocated for the work, and two business-critical applications approaching end of support.

This situation is common. .NET follows a predictable release schedule with defined support periods, so every application built on the platform has an upgrade clock from the day it goes live. In .NET development outsourcing, however, that responsibility is often left unclear.

Contracts usually cover features, bug fixes, and service levels, while runtime lifecycle management is left open. The result is that upgrade costs and risks fall back on the client, often when there is very little time to plan.

How the .NET Support Clock Works

Microsoft releases a new major version of .NET every November. Under the .NET support policy, even-numbered releases receive Long Term Support (LTS) for three years, while odd-numbered releases receive Standard Term Support (STS) for two years.

The current schedule is:
  • .NET 8 (LTS): Released in November 2023, with support ending November 10, 2026.
  • .NET 9 (STS): Released in November 2024, with support ending November 10, 2026.
  • .NET 10 (LTS): Released in November 2025, with support ending November 14, 2028.

Applications also need to run on the latest patch release for their .NET version. Microsoft releases these updates monthly on Patch Tuesday. Once a version reaches end of support, it no longer receives security fixes.

For any .NET software development effort, this creates a regular maintenance cycle. Applications need a major upgrade every two to three years, with monthly patches between major releases.

Why Upgrades Fall Through the Contract Gaps

Outsourcing contracts are usually built around deliverables. They define which features will be developed, which defects will be fixed, and what service levels the partner will provide. Runtime lifecycle work does not fit neatly into these categories.
  • It is not a feature. An upgrade may not add anything visible to users.
  • It is not a defect. The application may work perfectly even when its runtime is nearing end of support.
  • It is not a service level. Uptime and response times do not indicate whether an application is running on a supported version.
  • It affects multiple components. Runtime versions, SDKs, NuGet packages, frameworks, hosting environments, and CI/CD pipelines may all need changes.

When the contract does not define ownership, both sides can make different assumptions. The development partner may expect the client to request and pay for upgrades, while the client may assume keeping the application current is part of ongoing maintenance.

What an Upgrade Actually Involves

Moving from .NET 8 to .NET 10 may be relatively straightforward for a well-maintained application, but it is rarely just a matter of changing the version number.

A typical upgrade may involve:

  1. Updating the target framework across all projects.
  2. Updating NuGet dependencies, including third-party libraries that may introduce breaking changes or require their own upgrades.
  3. Addressing breaking changes in ASP.NET Core, Entity Framework Core, and other frameworks.
  4. Updating build and deployment pipelines, container images, and hosting configurations.
  5. Running regression tests covering functionality, performance, and security.
  6. Updating monitoring, logging, and observability configurations where required.
  7. Deploying across environments with appropriate rollback plans.

For .NET enterprise application development, the work can be more involved when several applications share libraries or infrastructure. Teams also need to coordinate upgrades with existing release schedules.

Desktop Applications Have Their Own Clock

.NET desktop application development using Windows Forms or WPF on modern .NET follows the same support schedule.

Desktop applications bring additional challenges. They may need to be deployed to many user machines, which can require installer changes and compatibility testing across Windows versions and hardware configurations.

Some organizations assume desktop applications can remain on older runtimes because they operate within the corporate network. That does not eliminate the risk. An unsupported runtime can still create a security exposure, especially when the application handles sensitive information or connects to external services.

The Real Cost of Unowned Upgrades

When nobody clearly owns runtime upgrades, the costs can show up in several ways:
  • Emergency projects that need to be scoped and priced at short notice.
  • Security exposure when applications continue running after support ends.
  • Compliance findings when audits identify unsupported software.
  • Growing technical debt when skipped upgrades make future migrations more difficult.
  • Dependency lock-in when outdated libraries prevent future upgrades.
  • Team disruption when planned feature work has to stop for an urgent upgrade.

Skipping an upgrade can also make the next one more difficult. Breaking changes and outdated dependencies accumulate, increasing the amount of work required later.

What Lifecycle Ownership Should Look Like in .NET Development Outsourcing

Contracts for .NET development outsourcing should make lifecycle responsibility explicit. Several elements can help.

A Runtime Roadmap

The contract should include a dated roadmap showing the .NET version used by each application, its support end date, and the planned date for moving to the next LTS release.

Monthly Patch Commitments

The agreement should define how quickly .NET patches will be tested and deployed after Patch Tuesday.

Dependency Management

NuGet packages and other dependencies should be reviewed regularly. The process should also include monitoring for known vulnerabilities and libraries approaching end of life.

Upgrade Budgets

A defined budget or effort allowance for major upgrades makes planning easier. The work should be agreed upon before the deadline rather than quoted when support is about to expire.

Readiness Assessments

A readiness review should take place well before the end-of-support date. This gives the team time to identify breaking changes, outdated dependencies, and other issues that could affect the upgrade.

Reporting

Regular reports should show runtime versions, patch levels, and dependency health across the applications covered by the contract.

Building .NET Custom Software Development for Upgradability

The easiest applications to upgrade are usually the ones designed with future changes in mind.

.NET custom software development teams can reduce future upgrade effort by:
  • Choosing well-maintained dependencies with active support and clear release histories.
  • Avoiding unnecessary custom forks of open-source libraries.
  • Maintaining strong automated test coverage, so regressions are found early.
  • Using infrastructure as code for hosting and deployment pipelines.
  • Keeping analyzers and warnings clean, so deprecated APIs are identified early.
  • Documenting architecture decisions that could affect future upgrades.

These practices should be part of the standard development process rather than treated as optional work.

.NET Framework Applications are a Separate Problem

Many organizations still operate applications built on .NET Framework 4.x, which follows a different support model.

.NET Framework 4.8.1 is delivered as part of Windows and is supported for as long as the Windows version on which it runs. That can make it tempting to leave older applications untouched, especially when they continue to work reliably.

The risks often come from the surrounding technology. Libraries may stop receiving updates for .NET Framework, developers with experience in older technologies such as Web Forms and WCF can become harder to find, and new cloud services and SDKs increasingly target modern .NET.

Older .NET Framework applications also cannot take advantage of some of the cross-platform hosting and container options available with modern .NET.

These applications should have an explicit lifecycle plan. Some may need a planned migration to modern .NET, with the work estimated and scheduled in advance. Others may be stable enough to remain on .NET Framework for the foreseeable future, provided they have a defined support arrangement and a retirement plan.

The worst option is to leave them without an owner. Over time, they accumulate risk until a security issue, hosting change, or other dependency forces an emergency rewrite.

Pricing Models for Lifecycle Work

Clients and development partners can structure lifecycle work in several ways.

A fixed monthly maintenance fee can include patching and minor dependency updates for stable application portfolios. A separate fixed-price upgrade can cover each LTS migration and provide predictable budgeting for major changes. A capped time-and-materials model can work when application complexity varies significantly.

The specific model matters less than agreeing on it early.

An upgrade planned well in advance can be scheduled around business cycles and other projects. Waiting until a few months before end of support leaves less room to negotiate, plan, test, and deploy.

LTS or STS?

Some teams choose STS releases to gain access to newer features sooner. The tradeoff is a shorter support period and a more frequent upgrade cycle.

For most business applications, LTS releases provide a simpler approach. Teams can plan around a longer support window and establish a regular upgrade cycle.

Organizations that choose STS should account for the faster cadence in their development and outsourcing agreements.

The fact that .NET 8 and .NET 9 reach end of support on the same date also shows how release choices can affect planning. Organizations running applications on both versions may face the same deadline for multiple upgrades.

Using AI Tools for Upgrades

AI coding assistants can help with parts of the upgrade process. They can identify potential breaking changes, suggest code updates, and generate tests.

Google's 2025 DORA report found that around 90% of technology professionals use AI in their work. The report also describes AI as an amplifier of existing team strengths and weaknesses.

That applies to .NET upgrades as well. AI can make upgrade work faster when teams already have good tests, reliable deployment pipelines, and healthy dependencies. It does not replace planning, regression testing, or clear ownership.

Questions to Settle with a Development Partner

Before signing or renewing a .NET outsourcing contract, clients should clarify:
  • Who tracks .NET and dependency support dates?
  • Are monthly patches included, and how quickly will they be applied?
  • How are major version upgrades scoped, priced, and scheduled?
  • What testing is included with each upgrade?
  • How is dependency health reported?
  • What happens if an application reaches end of support before the upgrade is complete?

Clear answers make it easier to plan budgets and avoid last-minute surprises.

A Representative Fix

Return to the logistics company from the opening example.

The company renegotiates its agreement with the development partner. The new contract includes a runtime roadmap for both applications, monthly patching within ten business days, quarterly dependency reviews, and a fixed-price upgrade to .NET 10 scheduled well before November.

Future contracts also include an upgrade allowance for each LTS cycle, with readiness assessments conducted well ahead of every end-of-support date.

The .NET 10 upgrade is completed on schedule. The next upgrade, to .NET 12, is already included in the roadmap and has a budget allocated to it.

The important change was not just the upgrade itself. The company made runtime lifecycle management part of the ongoing ownership model.

Measuring Lifecycle Health

Organizations can track a few practical measures to understand how well their .NET portfolio is being maintained:
  • Share of applications running on supported .NET versions
  • Patch latency: Time between Patch Tuesday and production deployment
  • Dependency health: Number of outdated or vulnerable packages
  • Upgrade lead time: Time between upgrade completion and the end-of-support date
  • Upgrade cost trend: How upgrade costs change from one cycle to the next

.NET custom software development comes with an upgrade clock from the first release. With .NET 8 and .NET 9 reaching end of support in November 2026, that clock is becoming harder to ignore.

Outsourcing contracts should define who owns runtime lifecycle management, how patches will be handled, when upgrades will happen, and how the work will be funded. Making those responsibilities clear early keeps applications supported and makes upgrade costs easier to plan.

Before the next contract renewal, ask a simple question: Which clause says who moves the application to the next LTS release?