Structuring Rails applications: the Modular Monorepo Monolith
Root Insurance runs their application as a monolithic Rails application – but they've modularized it inside its repository. Here is their approach in summary:
- Keep all code in a single repository (monorepo)
- Have a Rails Engine for each logical component instead of writing a single big Rails Application
- Build database-independent components as gems
- Thus: gems/ and engines/ directories instead of app/
- Define a dependency graph of components. It should have few edges.
- Gems and Engines can be extracted easier once necessary.
Advantages over a classic Rails monolith
- By (automatically) only requiring expected/allowed dependencies in tests, components cannot accidentally use (i.e. depend on) code they're not allowed to
- Onboarding is easier because of the clear separation and dependencies. No need to know the whole application.
- Faster test runs, because only dependent components need to run.
- A growing team can still keep up the development pace because developers concentrate on specific components. Merge requests target a specific component.
Advantages over a distributed application setup (multiple repositories, multiple applications)
- Everything is still deployed at once. No need to orchestrate branch merges and deploys across N repos.