Phil Booth

Existing by coincidence, programming deliberately

FxA monorepo migration

Historically, the Firefox Accounts (FxA) codebase was organised as separate repositories because it's deployed as separate microservices in production. However, that arrangement caused us some nagging issues as developers, so we decided to migrate the code to a monorepo instead. This post discusses why and how we did that, and how things turned out in the end.


There were three main problems with the many-repo approach.

With the imminent arrival of new recruits on the FxA team, we decided to take the hit and pull all of the code in to one place.


Our hard requirements for the move were that all of the commit histories must be preserved, the most recent tag for each service should be copied too and that CI should run tests for all downstream consumers when their upstream dependencies were changed. Danny Coates took the bull by the horns and wrote a script to do the actual work. We played with that until we persuaded ourselves we'd thought things through properly, then we fixed a date to migrate the code for real.

There could be no going back after that point, as issues were to be moved, pull requests re-opened, code landed and old repositories archived. We opted to do the move immediately after cutting the release for FxA train 134, to give ourselves some breathing space to work through any problems before cutting train 135. Or at least, that was the theory. In practice, we had to cut point releases for train 134 so a lot of that breathing space was lost.

After the code was moved, the next priority was to ensure we had a release script that worked from the new monorepo. This meant working for both JavaScript and Rust services, so probably warrants a separate blog post in its own right, but you can find the finished script here.


It's fair to say we underestimated how many problems might occur as a result of this migration. For example, some of the unexpected issues were:

Additionally, we haven't yet done some of the things the monorepo was designed to enable, such as standardise a mechanism for cross-package dependencies or unify the lint rules for all our packages.

Ultimately, it's become clear the migration will be a gradual process carried out over a number of months rather than an instant cutover. The long-term benefits are all still available but the journey to reach them is ongoing!