# Monorepo

## Why?

This approach helps manage complexity by applying best practices organization wide. This delivers consistency and predictability in our code, while also maximising the ability to share code between projects, it is easier to configure code validation and tests that is performed for all projects.

It's also much easier to make changes to shared code in a monorepo, since we can find and test all usage, with most changes automatically verified in CI. Compared to a multi-repo setup where we need to version every change, where different projects end up depending on different versions of the package, and need to manually update, which gets more risky the farther they fall behind.

In a monorepo, best practices, dependencies and shared code are updated for all projects at the same time.

## How?

We've enumerated many of the long term benefits of using monorepos. However, they skimp on the challenges of monorepos. The good news is that how we deal with these challenges brings even more benefits.

When all projects, old and new, are constantly kept up to date with best practices, shared code and dependencies, we need a high degree of confidence that nothing breaks when we change something. Also, we need to know which projects are affected by a change and should be deployed. I.e. we don't want to deploy all projects when someone pushes a change README.md. By using a monorepo tool that provides a caching layer and tracks dependency graphs, the CI can be optimised to only test projects which are affected by a change. This also allows us to deploy only the projects that are affected by a change.

Minimize dependencies and versions across projects for consistency, security, and performance. Document architectural decisions. Use a single package.json in the monorepo root to list all dependencies, allowing for phased migrations when changing dependencies.

## Branching strategy

Everything on main should be stable and ready for release. Work is performed on feature branches, which need to pass Continuous Integration checks and code reviews before they can be merged to main. Larger features can be managed in two ways:&#x20;

* If the feature is isolated and unlikely to have conflicts, it can be developed on a long-lasting feature branch until it is ready for deployment.&#x20;
* If the feature touches a lot of code and is likely to have conflicts, we should try to split it into smaller feature branches that are reviewed and merged independently.&#x20;

The overall feature can be disabled in production, eg using feature flags. We use "squash and merge" to compress features into one commit on main. This gives us a clean git history and allows us to easily revert unstable features. When it's time to deploy to production, we create a release branch from main.
