Software Development Services

How We Upgraded Angular 16 to 21 Without Breaking Production

Many enterprise Angular applications still “work” — but quietly accumulate risk.

They run on older Angular versions, rely on deprecated patterns like NgModules, struggle with dependency compatibility, and demand increasing effort just to stay stable. At some point, the cost of not upgrading becomes higher than the upgrade itself.

Recently, at Covalience, we modernized a large Angular application by upgrading it from Angular 16 to Angular 21. This wasn’t a routine version bump — it was a deliberate modernization effort focused on long-term stability, performance, and maintainability.

Here’s what we learned.

Why the Angular modernization became unavoidable

For teams maintaining mature Angular applications, the challenges usually surface in familiar ways:

  • Rising effort for even small changes
  • Increasing friction with third-party libraries
  • Slower builds and inconsistent runtime behaviour
  • Difficulty onboarding new developers
  • Growing security and compliance concerns

In this case, staying on an older Angular version meant dragging technical debt forward with every release.

The goal wasn’t to chase the latest framework version — it was to future-proof the product.

Modernization is an architectural decision, not a version upgrade

One of the most impactful shifts in recent Angular versions is the move from NgModule-based architecture to Standalone Components.

Adopting this model required more than automated updates:

  • Over 150 module-based components had to be refactored
  • Shared module logic was redesigned into provider-based configuration
  • Lazy-loaded routing patterns were rewritten
  • Application bootstrap moved to a modern app.config.ts setup

This was the most complex part of the migration and also the most valuable.

The result was a clearer dependency model, reduced boilerplate, and a codebase that aligns with Angular’s forward-looking direction.

AI-assisted acceleration with human judgment

We used GitHub Copilot to accelerate repetitive and high-volume refactoring work:

  • Converting template syntax (*ngIf, *ngFor → @if, @for)
  • Updating routes to component-based definitions
  • Resolving TypeScript compilation issues surfaced during migration
  • Maintaining structural consistency across files

Using an AI-assisted approach, we estimate we achieved ~4× productivity gains, but every change was still reviewed and validated by experienced engineers before it reached production. Modernization at scale still requires architectural decisions that tools alone can’t make. For example, migrating from an NgModule-based structure to Standalone Components required an explicit architectural direction from us, not something AI would do automatically.

A phased approach minimized production risk

Rather than jumping directly from Angular 16 to 21, we followed a sequential upgrade path (16 → 17 → 18 → 19 → 20 → 21).

While a direct upgrade may appear faster, it would have combined multiple generations of breaking framework changes, dependency shifts, and architectural updates into a single release significantly increasing production risk.

This phased approach allowed us to:

  • Isolate breaking changes introduced by each Angular version instead of debugging multiple issues at once
  • Continuously validate real application behavior using a test–fix–proceed model
  • Maintain stable, well-defined rollback points through disciplined commits
  • Verify Node.js and third-party dependency compatibility incrementally using nvm (Node Version Manager)

By upgrading step-by-step, we avoided large, irreversible deployments, compound runtime failures, and hard-to-diagnose production issues that often emerge only after real user traffic hits the system.

What changed after the upgrade

From a development and maintenance standpoint, the results were clear:

  • Significantly improved maintainability due to cleaner architecture
  • Higher consistency across components, reducing defect rates
  • Simpler dependency management and routing configuration
  • Better developer experience, especially for onboarding

Most importantly, the team now works on a platform that is aligned with Angular’s roadmap, not fighting against it.

Key takeaway for engineering and product leaders

Angular modernization isn’t about “being on the latest version.”

It’s about:

  • Reducing structural risk by redesigning the system so future changes are easy, safe, and predictable.
  • Creating space for faster delivery

Delaying these upgrades doesn’t avoid cost; it quietly compounds it.

Teams often reach out to us when modernization feels risky or overwhelming. In our experience, the right strategy and phased execution make it predictable and controlled.

If you’re maintaining an Angular application on an older stack and weighing your options, we’re always open to exchanging perspectives on what a safe modernization path could look like.

About the Author

Simrat Pal Singh
Dev Manager - Software Engineering
Covalience
Simrat Pal Singh is Development Manager of Software Engineering at Covalience, where he works across all development practices, including .NET, open-source backend and frontend technologies, and mobile platforms. With over 20 years of experience in software development and more than 15 years at Covalience, he helps teams deliver high-quality software by setting clear standards, building the right processes, and making sure engineers have what they need to do their best work. In this role, Simrat drives engineering excellence through well-defined development standards, coding practices, and security processes that evolve alongside the business. He partners with practice leads as Training Coordinator to keep learning programs current and meaningful, and works closely with the leadership team on skill development and career progression. He also engages directly with clients and stakeholders to understand business challenges and translate them into clear, actionable requirements for development teams.
On this page