The Great Migration: An Angular to React Migration Two Years in the Making
If you’ve been following the VTS blog, you may have stumbled across this post from Kyle Holzinger where he detailed the thought that went into our decision to move off of AngularJS. Since that post was written, the VTS engineering team has spent the last 2 years working on our migration off of the framework. I’m pleased to say that as of September this year, AngularJS is no longer part of the VTS application. This was a massive lift involving many teams, tools, and techniques.
There are many great articles out there about how to migrate a large AngularJS application to React, so I’ll focus this post on what’s more interesting and uncharted; how we overcame the challenges of planning and prioritizing a project of this scale across 10+ teams and 70+ engineers. Whether you’re interested in a similar migration, or you want to see how to move mountains inside your product org, I hope this post will have some helpful learnings that apply to you.
Humble Beginnings
When we first started this project, the sheer size of it was daunting. The VTS application is a large monolith; our JavaScript application alone clocks in close to 250K lines of application code. Given how large our application is, a “big bang” migration would have been impossible. We needed an approach that would allow us to continue to evolve our product while making measurable progress towards a full React application.
VTS has many teams, most of which are focused on product development (experience squads) and a few dedicated to our platform as a whole (platform squads). Before work from the experience squads could begin, we needed tooling that could support an incremental strategy and knew that a few pieces of groundwork would need to be in place for them to be effective. We had our Front End Platform squad spike on the general strategy for the migration. They decided to leverage a library that would allow us to render React components inside of an AngularJS tree (react2angular). This allowed us to start with very basic components at the leaves of the DOM tree and ship incrementally until an entire page or vertical had been migrated.
We had already been maintaining a design system / component library in AngularJS . We didn’t want our experience squads spending their time rebuilding it. So the Front End Platform team migrated all of our basic buttons, inputs, tables, and other components so that experience squads could dive in headfirst to migrate their areas of ownership within the application.
The Real Work Begins
With those two pieces in place, we were ready to begin breaking up the project into parallel tracks. There were many ways we could break the work up, and they all had trade offs. Creating tickets around individual files could have worked, but our Angular app resembled an undirected graph where true leaf nodes were rare. This meant that migrating a file would often take several pull requests with multiple dependencies to finish. We chose instead to create big tickets based on routes themselves (roughly 100 tickets, some of these ended up being turned into their own epics!). These were often too large, but mapped cleanly to feature teams within the org and offered a jumping off point to dive in deeper and slice up the work in grooming.
Initial progress was slow. It turns out that creating tickets and sending them into each team’s backlog is not a recipe for success for an initiative this large. It’s not that our teams didn’t care about the migration… there just weren’t any company wide goals to incentivize teams to make tradeoffs against existing product roadmaps. Much like building software, our approach to tracking, managing, and making progress on this initiative needed to evolve and become more sophisticated over time.
It Started With A Whiteboard
After several months of having broken ground on the project, we felt like we weren’t making much of a dent. A fellow Engineering Manager suggested that we make our progress more transparent so that the entire organization could see it and be more motivated to contribute. Rather than go with something high-tech like monitors around the office, I decided as an MVP (minimum viable product) to just draw a progress bar on the big whiteboard in the center of the engineering floor at VTS. It seemed simple, but this was a turning point for velocity on the project.
About 6 months into the project, we were sitting around 20% complete, and this was only tracking the migration of components! At this rate, it was going to take us at least 3 more years to finish. We realized we needed to get more serious about the project. We needed a program.
Getting With The Program
A program is a tool for managing major projects that require substantial ongoing investment. There are a lot of moving parts and investment to getting a program right, so this is not a silver bullet to every large engineering problem. For us however, it was absolutely the right decision to invest in. Our program consisted of a few key pillars that differed from our early approach.
- Greater investment in tracking: In order for teams to set goals for themselves, we needed tracking that went far beyond our existing JIRA setup. Because we were migrating one component at a time, oftentimes many migration PRs would need to happen before a file could actually be deleted. For that reason we decided to assign each file to a team, but track the number of lines of Angular they still needed to migrate. This level of granularity may seem extreme, but it was the only way to more accurately reflect the work going into the project. We took this data and were able to create customized dashboards for each team that visualized their progress and organized their remaining work by feature areas. One of the most interesting things to come out of this exercise was the disparity in equity of ownership between teams that had gone completely undetected until then. In some cases, between two equally staffed teams, we’d find one owned 2x the front end footprint in terms of lines of code. The React migration had side benefits in allowing us to redistribute code ownership inside the organization as well.
- Guild & Support Networks: Around the same time as rolling out the team based dashboards, we decided to build a support network for the tech leads & product managers on each team who were responsible for delivering on their migration goals each quarter. This took the form of a React guild, a group with its own Slack channel and a standing meeting to report on progress, discuss learnings, help monitor / mitigate regressions, and build solidarity around the initiative.
- Marketing Campaigns: For our initiative to be successful, we needed React to be a part of the cultural zeitgeist of VTS. To accomplish this, we made sure to have a standing section of sprint demos for progress updates and big announcements of milestones. We even reported semi-regularly at company all hands. All of this amounted to a huge uptick in the general familiarity with the project. I knew we were successful when someone from the accounting department asked me how the migration was going while grabbing coffee in the kitchen.
- Executive Sponsorship: I like to cite this as the single biggest mover of the migration. Having our executive team acknowledge the importance of the migration — so much so that we placed goals of the migration as top level department OKRs — changed the conversation completely. Suddenly, teams had the ammunition they needed to prioritize React migration work over other product work to actually make significant progress. Product and technology leaders of teams had to report on their progress on a regular cadence. It was a radical shift that made the migration part of the conversation every single sprint.
To visualize the impact of each of our “evolutions” of our React program, here is a diagram of our relative velocity (tracked across teams) as we introduced changes to the React program. You’ll notice that certain tools moved the velocity needle for teams differently — it was important to monitor and adapt, just like any agile software development process.
The Home Stretch
As some teams started to close out their migration backlogs, we began to see the light at the end of the tunnel. Our Front End Platform team rallied around the cause, and became flexible resources embedded within other teams to help their lagging velocity or particularly tricky migrations. Using this approach, we were able to fully migrate the full “tree” structure of Angular components to React in Q1 of 2020 (during COVID no less)! This was a major accomplishment and we celebrated accordingly.
And then reality set in. Our app was being powered by React components, but Angular was still being used to handle network requests, routing, and several other critical faculties. We couldn’t actually realize the benefits of proper bundle splitting, a modern single-framework ecosystem, and lessened developer overhead without fully ripping out Angular. After all this work, we also had another challenge on our hands — program fatigue. We had just successfully redirected almost the entire engineering organization into placing time and energy against this migration for more than a year. This was an extremely costly proposition, and we needed to let teams get back to building and delivering new value for our customers. Thus we assembled a “tiger team” of React evangelists with the specific goal in mind of being free of Angular by the end of the year. We called the team “Project Roundedge”, because well, we were removing angles afterall.
Project Roundedge
Over the course of 3 months, the team moved route by route in a “vertical” approach, replacing each service, dependency, and finally the routing layer for various pages. This allowed us to set up boundaries for QA and testing to make ensuring quality while effectively replacing a major layer of our infrastructure a little less daunting.
This part of the project went a lot smoother and more predictably thanks to all the discovery we had done earlier in the migration. At the start we knew more or less what we’d need in terms of project tracking, tickets, and planning work. We also better understood where all the difficult nooks and crannies were, and how to better estimate the unknowable. Successfully building and running a program builds a lot of great muscles which can be used on even smaller scale projects.
What’s Next?

With AngularJS fully out of the picture, we’re now primed to dig into what VTS can do with a single framework. Already we’ve begun to split our bundles more aggressively and examine our routing and state management solutions more closely. The opportunities are endless and it’s one of the most exciting times to work on the front end of our VTS product. There’s never been a better time to come join us, so head on over to our jobs page and see what’s open!