Luca Morelli
Software analyst and developer
Team lead

Migrating to current stacks: risks analysed first, then verifiable steps.

I no longer take on maintenance of technically obsolete projects, but I often move them onto current technologies. It is work that needs particular care: a version change often hides libraries to replace, architectures to restructure and configurations to rethink.

Analysis before codeDependencies, licences and risks assessed before choosing the path.
A minimal product, earlyA few features, but runnable, to validate the new architecture.

Why now

In environments with strict security controls, a version that no longer receives updates soon becomes a problem.

Once support ends, security fixes stop. Where security and privacy constraints apply, this can block a release or come up in an audit.

  • .NET 8 and .NET 9: end of support on 10 November 2026. Microsoft recommends moving to .NET 10, supported until November 2028.
  • Angular 20: end of long-term support (LTS) on 28 November 2026. Each Angular major version is supported for about 18 months.
  • AngularJS: unsupported since the end of 2021.

What actually gets migrated

01

The version

The most straightforward case: the same product, in a more recent version.

Even here the jump can be large. Moving from AngularJS to Angular essentially means rewriting the user interface; between Angular versions you go one major version at a time, checking the breaking changes at each step.

Typical paths

  • AngularJS → Angular
  • Older Angular → current Angular
  • .NET Framework → current .NET
  • Unsupported .NET versions → .NET 10
02

The libraries

Parts built on obsolete libraries often have to be rewritten, mostly on the client side but on the server too.

Many JavaScript libraries hide heavy re-engineering behind a version change. On the server, some have changed licence: this is the case for applications using iTextSharp 4.1.6, the last LGPL version. Later versions are available only under the AGPL or a commercial licence, and for current .NET there is only an unofficial port of 4.1.6.

For each component

  • How it fits into the rest of the architecture
  • Licence of the compatible version
  • Upgrade it, replace it or rewrite the code that uses it
03

The architecture

Adopting current standards means restructuring, not just recompiling.

Many .NET Framework applications use outdated patterns, such as static classes and hand-built dependencies, whereas current .NET is built around dependency injection. Some technologies also have no direct equivalent.

I have migrated Web Forms applications to modern web apps, converting the code-behind into Web APIs, and in one case to Blazor, to stay on an all-Microsoft stack. In the same way I have moved WCF services to REST APIs: here the delicate part is often the data format, because clients took WCF serialisation for granted.

From my experience

  • Web Forms → web app with Web APIs
  • Web Forms → Blazor
  • WCF → REST APIs, compatible with existing clients
  • Static code → dependency injection
04

The move to the cloud

From a traditional server to the cloud, migration is not only about the application.

Configuration, architecture, permissions and data access have to be analysed and rethought to reach a cloud-ready solution. These are the elements I have dealt with in migrations of this kind.

What needs rethinking

  • Configuration and secrets, from local files to dedicated services such as Key Vault
  • Permissions, from Windows accounts to managed identities
  • Stored procedures and database features not available in the managed service, such as scheduled jobs, cross-database queries and CLR assemblies
  • Files on disk, in-memory sessions and scheduled tasks, moved to storage, a distributed cache and services such as Azure Functions

The method: risks first, then gradual steps

  1. Up-front analysis

    An inventory of dependencies, libraries, licences and integrations. For each one, decide whether to upgrade, replace or rewrite it, and which restructuring is needed.

  2. Minimal product

    The features needed to prove the new architecture holds up, running as early as possible.

  3. Feature by feature

    A step-by-step plan, with regression tests at every stage.

  4. Stakeholders involved early

    The people who use the system start trying the migrated parts as soon as they are ready.

  5. Old and new side by side

    Where possible, the two applications run in parallel. From AngularJS to Angular, users worked with both, to compare them and for the features not yet migrated.

Every migration is a unique path: it depends on where you start, where you want to get to and all of these factors. What does not change is the method: risks analysed first, gradual and verifiable steps.

The initial analysis can also be a stand-alone engagement. More often, with direct clients, it is the first step of a path that leads all the way to the migrated application in production, without the client having to take development in-house.

Coding agents and migration

In migrations I use coding agents with the spec-driven method: starting from the existing code I set the sequence of steps, and alternate the tests run by the agent with hands-on checks.

The agent is least reliable on legacy code, which is exactly where the up-front analysis matters most. Microsoft itself has replaced its upgrade tool, Upgrade Assistant, with an AI-based agent.

How I use coding agents in migrations

Have an application to move to current .NET or Angular?

Detailed CV and references available on request.