AngularJS to React Migration Case Study: How We Did It Without a Big Rewrite
Real AngularJS to React 19 migration case study. Strangler pattern, incremental delivery, no big-bang rewrite. Timeline, gotchas, and 12-month results from an Australian SaaS platform that ran both frameworks side by side during the transition.
Kasun WijayamannaFounder & Lead DeveloperPostgraduate Researcher (AI & RAG), Curtin University - Western Australia
AngularJS (Angular 1.x) hit end-of-life on 31 December 2021. That was over four years ago. Yet in 2026 we still get calls from Australian businesses running production applications on AngularJS, because the migration path always looked too big, too risky, or too expensive to justify.
This case study is an anonymised version of a real client engagement, a mid-market Australian SaaS platform with roughly 40,000 lines of AngularJS code, ~20 active screens, and a small internal team who could not stop shipping features to migrate. We share it because "big-bang rewrite" is not the only option, despite what most agencies quote.
The starting point
The application was a B2B portal serving around 3,500 daily active users. Built in 2015 on AngularJS 1.5, it had accumulated the usual signs of a codebase past its use-by date:
Dependency versions frozen because upgrades broke things, the last npm install that worked cleanly was 2019
Security scanners flagging 40+ high-severity vulnerabilities in transitive dependencies
Hiring pipeline dead, nobody wants to work on AngularJS in 2026 unless the salary is 30% above market
New feature velocity slowing quarter over quarter as the codebase resisted change
Increasing incident rate, outages traced back to legacy code that only two people understood
The business had rejected two rewrite quotes previously: one 18-month project at nearly $1M, one 12-month at $650K. Both would have frozen new-feature development for the duration. Neither was politically survivable.
Why not just rewrite from scratch
A big-bang rewrite of 40,000 lines of production code is not just expensive, it is disproportionately risky:
The old system keeps changing while you build the new one (moving target)
Business rules encoded in the old codebase are not fully documented anywhere else (institutional knowledge risk)
Cutover is a single high-stakes weekend that nobody sleeps through (rollback risk)
The people who know the old system are the same people you need to build the new one (bandwidth risk)
Every one of those risks compounds if the rewrite runs long, and rewrites always run long.
The migration approach, strangler pattern
Instead of rewriting the entire app, we used the strangler fig pattern: the AngularJS app stayed alive, and we incrementally replaced screens with React equivalents behind a routing shim. Users saw a mix of AngularJS and React screens during the migration and never noticed which was which.
The high-level architecture:
Reverse proxy in front of both apps, routing URLs to either the AngularJS bundle or the new React app based on a routing table.
Shared session and API layer, both apps hit the same backend, both authenticated via the same JWT flow.
New features shipped in React from day one, no more AngularJS code added after week 4.
Existing screens migrated one at a time, prioritised by (a) traffic volume, (b) rate of change, and (c) security exposure.
Key architectural decision: we did NOT use ngReact or any AngularJS-in-React bridging library. Every bridging library adds runtime complexity and eventually blocks you from removing AngularJS. Two separate apps behind a shared proxy proved simpler and more decoupled.
Timeline and milestones
Month
Milestone
State after
0–1
Set up React 19 + TypeScript scaffolding, reverse proxy, shared auth
Final AngularJS screens migrated, reverse proxy simplified
AngularJS bundle removed, single React app
Total elapsed time: 10 months. Roughly half the timeline of the cheapest rewrite quote, and new features shipped continuously throughout.
What went well
Zero downtime. No cutover weekend. Users were on both apps for months without noticing.
Continuous feature delivery. The product team shipped 14 new features during the migration, all in React. Sales did not have to wait.
Risk containment. Every migration was individually reversible. When one report screen behaved differently in React (rounding issue), we routed back to AngularJS in 20 minutes while we fixed it.
Hiring unblocked. By month 3, we were interviewing React developers and had one hired by month 5. Would not have been possible on the AngularJS codebase.
What went sideways
Session cookie collision. AngularJS and React apps sharing session state via cookies looked simple until subtly different cookie flags broke the auth flow on Safari. Cost us three days.
Analytics double-counting. During the transition, some pageviews were fired by both apps. Business dashboards showed inflated numbers for two weeks before we caught it.
The last 10% took 30% of the time. Edge-case screens (batch operations, seldom-used admin flows) had the most institutional knowledge baked in and the fewest tests. Standard for migrations.
Design drift. Six months in, the React app looked subtly newer than the AngularJS one. Product management had to make a call: brand refresh mid-migration, or defer. They deferred, and it looked slightly inconsistent for four months. Worth it.
Results after 12 months
Deploy frequency: up from ~2/month to ~15/month
P95 page load time: down from 3.4s to 0.9s
Critical security vulnerabilities: down from 40+ to zero
Time to onboard a new developer: down from ~6 weeks to under 2
Feature backlog burn rate: up ~2.3x on comparable feature complexity
The migration paid for itself in year one on incident reduction and developer time saved. The compound value, faster feature delivery, retention of senior engineers, ability to scale the team, will keep compounding.
Lessons for your migration
Do not try to bridge the frameworks in-process. Two apps behind a proxy is boring and it works.
Migrate by traffic and change-rate, not by "logical grouping". The screens users touch most and change most often are where the ROI lives.
Ship new features in the new stack from week 4. If new features go into AngularJS during migration, the migration will never end.
Budget for the last 10% to feel like 30%. Do not celebrate at 90% complete.
Keep the design consistent, or deliberately inconsistent. Trying to visually match the old app in the new stack burns weeks of design time. Just ship the new design.
If you are running AngularJS (or Angular 1.x, IE-era jQuery apps, or any other legacy frontend past end-of-life) and want to talk through a strangler migration, our legacy software modernisation service page covers the specific approach we use. And the rebuild vs patch guide covers the decision framework for whether now is the right time.
Kasun WijayamannaFounder & Lead DeveloperPostgraduate Researcher (AI & RAG), Curtin University - Western Australia