Structuring Rails applications: the Modular Monorepo Monolith

The experience of Evil Martians discouraged us and we're not pursuing this approach any more. See their engems tool.

Root Insurance runs their application as a monolithic Rails application – but they've modularized it inside its repository. Here is their approach in summary:

Strategy

  • 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.

Other resources

  • https://www.airpair.com/ruby-on-rails/posts/ruby-on-rails-the-modular-way
  • https://engineering.gusto.com/building-toward-a-modular-monolith
  • https://railsconf.com/2020/video/vladimir-dementyev-between-monoliths-and-microservices
Dominik Schöler About 4 years ago