Mono Repo β
π Why we choose a Monorepo? β
We opted for a monorepo to centralize and simplify the management of:
- π οΈ Application code: all apps (frontend & backend) live in the same repository, making it easier to navigate and understand module dependencies.
- βοΈ Gradle conventions: shared build configurations ensure consistency and simplify maintenance.
- ποΈ Documentation: functional and technical documentation remain close to the code, reducing divergence risks.
- π¦ Shared libraries (tech-starters): internal tools, starters, and reusable components are transparently shared without the overhead of external versioning and publishing.
π Benefits β
β Immediate visibility of change impact
- Changes in a shared library are instantly reflected in consuming projects.
- The compiler signals immediately if a consuming project is impacted.
- Enables confident refactoring with immediate feedback via compilation and tests.
β Reduced version management overhead
- No need to publish internal artifacts for each update.
- Continuous updates without complex internal dependency deployments.
β Easier onboarding
- New contributor access code, shared libraries, and conventions in one place, accelerating ecosystem understanding.
β Technical alignment and consistency
- Technical improvements are applied consistently and immediately across projects.
βοΈ Known Limitations β
β οΈ Change coordination required: In a monorepo, developers can make changes affecting other teams directly. This speeds up alignment but requires informing impacted teams to avoid surprises. Not a big issue with this little Github project but let's keep it in mind.
β οΈ Potentially longer build times:
Building the entire repository can take longer than isolated builds, but is currently negligible for our project size.
β οΈ Not suited for very large scale:
Monorepos can become harder to manage as they grow in size or with many independent teams, but for our current project scale, the trade-off is acceptable.
ποΈ Best Practices β
β
Keep modules decoupled where possible to minimize unnecessary rebuilds.
β
Use clear module naming to ease navigation.
β
Automate pre-commit checks and CI pipelines to detect issues early.
β
Keep documentation near code and up to date with changes.
β
Use build caching technics to reduce build times.
β
Regularly review dependencies between modules to avoid tight coupling.
β
Communicate with other contributors when making breaking changes in shared libraries.
β
Regularly clean up unused modules to keep the repository lean.
TIP
More details in some Medium articles like here