DEV Community

Cover image for Why should you use a monorepo for your Product?
Sibelius Seraphini for Woovi

Posted on

Why should you use a monorepo for your Product?

Introduction

The choice of repository structure plays a pivotal role in shaping the efficiency and scalability of your projects.
A monorepo lets you break your monolithic codebase into well-defined domains or bounded contexts.

In this article, we will outline some benefits of monorepo for your product.

Shared codebase

The workflow to share code among multiple repositories is like this:

  • You create a pull request in repo A
  • you await the review of your changes
  • you merge your changes in repo A
  • you make a release to repo A
  • you update repo A dependency on repo B

You need 5 iterations to update shared code among polyrepos.
This is a workflow in a monorepo:

  • You create a pull request in monorepo
  • you await the review of your changes
  • you merge your changes in monorepo

In a monorepo, you only need 3 iterations.
However, you earn much than that, you make sure your code will work at first.
When updating a code in repo A, you can't share the changes will be enough for the repo B use case. You could need to go back and forth until you get it right.

New package vs new repo

It is simpler and easier to create a new package inside a monorepo than to create a new repo.
The new package will reuse all the infrastructure already in place. Linter, tests, CI/CD, automation.
The new repo will need to be created from a boilerplate that is probably outdated.
Most developers will avoid creating a new repo as it requires a lot of effort.

Unified Tooling

A monorepo lets you unify your tooling and codebase patterns.
You can have a single lint config, you can have a single CI/CD config. As a result, you have a more unified codebase.
You can use the same test and build configs among packages.

Centralized dependencies

You can keep all your dependencies updated in a monorepo. No need to update the same dependency in many repositories.

Bounded Contexts

You can use packages to provide a public API for each domain or context of your product. And keep the private API unexported.
This will make sure you don't couple your code too much.

Read more about DDD on monorepos here: Domain Driven Design using a monorepo

Refactoring and codemods

A monorepo makes it easy to refactor and apply _codemods _(transformation over AST) to reduce legacy code.
You don't need to apply the same refactor in many repos, just in a single repo.

In the final analysis

A monorepo lets you add more structure to your codebase as you grow. You can start your monorepo with one single package, and add more packages as needed.
You can have one package for each domain.
You can have one package for each service or lambda.
You can have one package for your design system.

How does your monorepo looks like?


Woovi
Woovi is a Startup that enables shoppers to pay as they like. To make this possible, Woovi provides instant payment solutions for merchants to accept orders.

If you want to work with us, we are hiring!


Photo by Amélie Mourichon on Unsplash

Top comments (6)

Collapse
 
lefttwixwand profile image
Vladyslav Horbachov • Edited

In 99.9999999% I hate monorepos.
It might be good at the start of your project, but at one point of time it might become a hell for developers to work in such space.
There are few things, which I don't like:

  • "Reusable" or "Common" infrastructure, like building, packaging and testing tools might limit your flexibility. Works - so don't touch it🤡 will be number 1 argument stopping you from some improvements. You want to change some tools to newer and more efficient? - you won't be able to do it step by step. You'll have to apply the change to all the projects in your repo, and the chance of something is going wrong is extremely high. The same is relevant not only for changing existing, but for adding something new. You always have to take in consideration the existing environment.
  • What if some of the projects in the monorepo require more flexible approach, then the other ones? For example - you want to deploy one specific project out of a bunch of others. How to do it? Be ready to create a separate pipeline for each project. As well as adding separate git tags to track changes and versions of each project in the repo.
  • Dirty git history and terrible navigation between version is what you'll see regularly with a monorepo.
  • And the last thing, which infuriates me the most - IT'S A MONOREPO!!!!
    • Your repo is quite big.
    • You're tracking the entire repo with tons of changes, which might be done by a different team and not affect you at all.
    • From my experience: when you want to build a part of the project - you're going to build the entire solution, just because "why not?". We have a common build infrastructure, so let's build all at once🎉
Collapse
 
skittishsloth profile image
Matthew Cory

No. We're actively moving away from a monorepo right now because it's a mess. I'll grant that it was mostly ad hoc, and maybe it would've been different if we went into it intentionally, but we didn't and it is what it is.

The main benefit in having multiple repos is that they're isolated. You can make changes to one without worrying about impacting another. You can version them easily - if there's a commit to this repo, you bump the version. If I want to upgrade a dependency in one project without upgrading it in another, it's simple - no concerns about different versions possibly clashing.

Lots of boilerplate? Script it. Create templates. Hell, just do it manually - you only have to do it once per repository.

Are your build files a lot of copy pasta, and you're worried about updating everything when there's a change? Not sure what build system you use, but surely it allows for some kind of plugin system. Use that. If I'm not mistaken, I think Gradle even recommends writing custom plugins for a lot of stuff you'd normally copy and paste, they want you to look at plugins as the "type" of project you're working on.

You're a coder! It's literally your job to take tedious crap and automate it. I don't care what you're writing, you're doing it so that a computer does something that a person can't or won't. Boilerplate and common build functionality is just another example of that.

Your update to your common library now involves more steps before you can use it. So make sure you have your changes tested and documented thoroughly, make sure it passes code review, make sure you don't have to go through it all again. Does that process take a long time? Then work it out with your team! Communicate! Figure out how you can speed up the overall workflow. Don't just hack around the roadblock - you're better than that. Fix it.

Also, make sure you're using good design patterns and principles in your code. You might be able to minimize work in your library projects if you developed them to be easily extended.

I'm sorry, but stuffing everything in a monorepo because you're impatient or don't want the "hassle" of dealing with separate projects is no solution.

Collapse
 
anubarak profile image
Robin Schambach

Wouldn't that be against DRY principles? What if I need my libraries in multiple projects? Do I have to make the changes in all monorepos and what's the benefit of this?

Collapse
 
the_real_osho profile image
Eric Ellingson • Edited

Then that wouldn't be a candidate for inclusion in a monorepo

Or, you could still include the package if the primary use is in that monorepo, and publish to a private package that can be pulled in elsewhere

Collapse
 
lefttwixwand profile image
Vladyslav Horbachov

Firstly, I recommend you to really think about your libraries. Are they really libraries?

  • Because if they just a common projects, and you're updating them every day - I don't see any purpose in making them libraries, and you can just store them in your main repo.
  • But if they are good designed, logically separated, independent - I would highly recommend you to separate the libraries into new repositories. Set up the competent distribution via some package management system according to your programming language, like node, nuget, pub, go modules and so on. Just looks at how the popular libraries been done on GitHub. Release of a new version - is a big event for users. They read the release description and "what changed". And what is important - the update might be absolutely "invisible" for the users. Because common interfaces of communication with library are still same. Changes are internal only.
Collapse
 
anubarak profile image
Robin Schambach • Edited

They are libraries otherwise I wouldn't have said it. They have their own repo, their docs, changelogs and so on.
That's why I wondered why they should be included into the main repo of every project instead of their own repo - as the article claimed somehow (the author corrected that in the comments but it wasn't clear at first)