Release management strategies in a monorepo

Greg Foster
Greg Foster
Graphite software engineer
Try Graphite

Table of contents

A monorepo houses multiple projects in a single repository. This setup simplifies code sharing and streamlines tooling but creates complexity in release management. Common challenges include high change volume, cross-team coordination, CI/CD bottlenecks, and maintaining a stable main branch.

Trunk-based development involves merging small, frequent changes directly into a central branch (e.g. main) and keeping it deployable at all times. Teams use short-lived feature branches or commit directly to trunk, supported by a fast and reliable CI pipeline.

For monorepos, TBD reduces integration overhead. Instead of coordinating across multiple teams before merging, everyone works on the latest code. Feature flags help merge incomplete features safely. This model requires strong test automation and continuous integration discipline.

Release branches are cut from trunk at specific points and used to stabilize code for deployment. This approach gives teams a freeze window for final QA and bug fixes without blocking ongoing development on trunk.

They're ideal for scheduled or coordinated releases. However, they require careful backporting and merging strategies to avoid drift between branches. In a monorepo, this can get tricky due to overlapping changes across multiple services.

In monorepos with many services, it's common to treat each as its own release unit. Each service has its own versioning, deployment pipeline, and potentially CI triggers that activate only when its directory is modified.

This setup requires clear boundaries between projects and a way to handle internal dependencies. Teams often use tools like Lerna, Yarn workspaces, or language-specific build systems to isolate and version components independently.

Some monorepos operate without internal versioning—building everything from trunk (e.g. Google). Others version each package independently using semantic versioning. Tools like release-please, Changesets, or Lerna help automate version bumps and changelogs based on commit messages.

To manage shared dependencies, monorepo teams often use internal package managers (npm workspaces, Gradle submodules, etc.) and enforce explicit dependency declarations. This reduces accidental coupling and helps teams adopt new versions on their own timeline.

Running all builds and tests on every commit doesn't scale. Monorepos need smarter pipelines that support:

  • Selective builds: Only build/test the affected projects (using path filters or dependency graphs).
  • Caching: Reuse results from unchanged components.
  • Parallelism: Split builds/tests across multiple workers.
  • Conditional deployments: Only deploy services that changed.

CI tools like GitHub Actions, Buildkite, and Bazel support these patterns. Trunk stability is key, so merge queues are increasingly essential.

Merge queues protect trunk from breaking changes by serializing PR merges. When a PR is queued, it's rebased on the latest trunk, tested in that state, and only merged if all checks pass. This avoids "green PRs" breaking when merged simultaneously.

Graphite enhances this with:

  • Stacked PRs: Developers can break large changes into dependent PRs (e.g., DB migration → API → frontend). Each PR is reviewed separately, and Graphite keeps them in sync automatically.
  • Optimized merge queue: Graphite tests stacks as a unit and merges them in batch if safe. This reduces CI load and speeds up integration.
  • Auto-rebasing: Graphite continuously rebases queued PRs on the latest trunk, avoiding merge conflicts before they hit main.

This model suits high-throughput monorepos. Developers can push large changes incrementally, get fast feedback, and trust that trunk will remain stable.

Here's a quick breakdown of useful tools by category:

CategoryExamplesRole in monorepo management
Build systemsBazel, Pants, NxIncremental builds, DAG-based test selection
VersioningLerna, Changesets, release-pleaseAutomate package versioning
CI/CDGitHub Actions, BuildkitePath-based pipelines, parallelism
Merge queuesGraphite, GitHub Merge QueueSerialized merges, test gating
Dependency botsDependabot, RenovateAutomate version bumps

Releasing software from a monorepo requires intentional strategy. Trunk-based development accelerates integration. Release branches offer stability when needed. Independent service releases give teams flexibility. Versioning and CI/CD must scale with your repo.

Tools like Graphite help maintain a stable main branch and manage complex workflows with stacked PRs and efficient merge queues. Whether you’re coordinating a massive deployment or shipping a small change, the right strategy and tooling can make monorepos a powerful foundation for fast, reliable releases.

Built for the world's fastest engineering teams, now available for everyone