Scaling GitLab for large monorepos

Large monorepos and heavy CI concurrency push self-managed GitLab sizing beyond headcount, with Gitaly as the component most affected. This page explains what changes, how to choose a starting size, and which workloads GitLab lists as performance risks.

On this page

Scaling GitLab for large monorepos: when headcount stops being the right sizing input

Large monorepos and heavy concurrent CI change GitLab sizing, so a user count alone is no longer a safe basis for hardware. GitLab's reference architectures run from 1,000 users at 20 API requests per second (RPS) up to 50,000 users at 1,000 RPS, which means two organizations with the same headcount can need very different environments. Plan around RPS, and count the monorepo clone traffic and pipeline activity that generate those requests alongside the people using the instance. This planning matters when your repositories are large enough that Git operations are expensive, when developers push and fetch many times a day, or when CI runs many pipelines in parallel against the same projects. Those patterns land mainly on Gitaly, which serves Git data, and on the Rails and Sidekiq tiers that handle API calls and background jobs. Ask your team to measure current request volume, clone and fetch frequency, repository size and peak pipeline concurrency, then match those figures to the reference architecture tables in the GitLab documentation before you pick a node count. This sizing exercise is not a substitute for load testing. A reference architecture is a starting baseline built on GitLab's own test workloads, and your monorepo's object layout, branch churn and CI job shape can behave differently. Confirm the target with a load test against a staging environment before go-live, and confirm current workload guidance with GitLab, since the documented targets can change between releases.

Which workloads GitLab lists as performance risks

GitLab's reference architecture documentation names workloads that strain an instance as load grows, and they often compound each other. A large monorepo is expensive to read, a busy pipeline fleet multiplies requests, and background jobs queue behind both. Treat this summary as a starting point and confirm the current wording in the reference architecture documentation before you size hardware.

High CI job concurrency

Each running job calls back to GitLab for job requests, logs, artifacts and status updates, so a burst of jobs multiplies API traffic and background work. Runner count, executor type and per-runner concurrency decide how fast that burst arrives. Record your peak concurrent job count over a typical month, including scheduled pipelines and merge trains. Ask whoever operates your runner fleet how autoscaling limits are set, because those limits cap the peak you need to plan for.

Very large repositories

Gitaly serves Git reads and writes for every repository, and a repository with deep history, large binary files or many refs puts sustained load on the node that stores it. Simultaneous clones, fetches and pushes from many developers and build systems are the usual pressure point. Check repository size, history depth, large file use and whether CI clones shallowly or fully. Find out whether your largest monorepo sits on a single Gitaly node, because that node becomes the bottleneck for everything stored on it.

Concurrent API request volume

GitLab's reference architectures are sized in API requests per second, from 20 requests per second for 1,000 users to 1,000 requests per second for 50,000 users. Automation drives much of that traffic through CI jobs, bots, dashboards, scripts and synced tools that poll endpoints. Measure your current request rate, counting automation as well as people. Identify integrations that poll GitLab on a timer and check whether they can use webhooks instead.

Sidekiq background job backlog

Pushes, merges, webhooks, notifications and cleanup tasks run as background jobs in Sidekiq. When job volume rises faster than Sidekiq processes can drain it, work queues up and users notice delays in merge requests, mirrors and pipeline status updates. Check queue depth and job latency during your busiest hour, not the daily average. Separating Sidekiq nodes from Rails nodes is one scaling option, and the decision should follow queue growth you have measured.

PostgreSQL and Redis under load

Every API request and background job reads or writes PostgreSQL, and Redis holds cache and queue data. As concurrency rises, database connection counts and query latency can become the first limit, and Redis memory and eviction behavior matter under pressure. The reference architecture documentation recommends a high availability strategy for 3,000 or more users and keeps PostgreSQL and Redis outside Kubernetes. Confirm connection limits and failover behavior with your database team before you add application nodes.

Starting large and scaling down: choosing an initial reference architecture

When you already know the repository size, the number of developers pushing and the CI job concurrency you expect at peak, you can translate that into requests per second and match it to a published reference architecture. The reference architectures run from 1,000 users at 20 API requests per second to 50,000 users at 1,000 requests per second, so headcount alone rarely tells you the right tier. Large monorepos and heavy pipeline fan-out raise Gitaly and API load well beyond what the user count suggests.

  • Estimate peak, not average: Use the busiest hour of a normal week, including release days, as the planning figure.
  • Count CI as load: Pipelines that clone a large repository many times per hour add Gitaly reads that users never see directly.
  • Size Gitaly separately: Confirm the storage and CPU needed for the repository size you are moving in, because it does not scale with user count alone.
  • Start at the tier that covers the peak: Choose the reference architecture whose requests per second target meets or exceeds your estimate.
  • Confirm the HA requirement: The documentation generally recommends high availability from 3,000 users, so check that the tier matches your availability needs.

Before committing, ask your DeployOpen or internal team to confirm the published node specifications for the chosen tier against your environment.

Sizing options for Gitaly and the Git tier

This table compares the three main ways to run the Git storage tier for a large monorepo: a single Gitaly node, sharded Gitaly and Gitaly Cluster with Praefect. Read each row against your repository size, failure tolerance and the user count where GitLab recommends high availability.

OptionFailure handlingOperational complexityWhen to choose it
Single Gitaly node on a Linux package installOne node holds the repositories, so a node failure stops Git operations until it is restored from backupLowest. Managed with the same Linux package tooling as the rest of the instanceSmaller user counts where a planned restore window is acceptable and the monorepo fits one node's disk and memory
Sharded GitalyEach repository lives on one storage node, so a failure affects only the repositories on that nodeModerate. You plan how repositories are distributed across storage nodes and rebalance them as the load changesSeveral large monorepos or many teams where spreading load across nodes matters more than automatic repository-level failover
Gitaly Cluster with PraefectRepositories are replicated across nodes, so the cluster can keep serving if one node failsHighest. Adds Praefect nodes, replication management and its own backup and restore considerationsRepository-level high availability is required, typically in the high availability designs GitLab recommends from 3,000 users
Heavy CI clone traffic on a monorepoLong clones and fetches compete for the same Git node, so slow responses can appear before any outageDepends on the option chosen. Watch Gitaly latency and saturation rather than only up or down statusConfirm with a load test against your own repository size and job concurrency before choosing the layout
Repository size and disk growthA very large repository increases restore time and replication time on every optionAdds planning for storage capacity, backup duration and rebalancing effortAsk the vendor or your own tests how backup and restore time scales for your largest repositories
Resource sizing for the Git nodeUndersized CPU or memory slows pack operations and can cause timeouts during peak pushes and clonesRequires monitoring of Gitaly resource use and a plan to increase capacityStart from the reference architecture that matches your user and request targets, then adjust for monorepo size

How to size and validate a large monorepo deployment

This sequence turns repository size, Git traffic and CI concurrency into a reference architecture choice, a starting size, load test evidence and a production monitoring baseline before any capacity is removed.

  1. Measure repository sizes and Git operation volume

    Your platform team records the size of the largest repositories, including history and LFS content, and the rate of clones, fetches and pushes across a typical business week, with peaks at release or month-end windows. Pull these figures from your current Git host, the repository storage on disk and any existing proxy or access logs. The step is done when you have a written inventory listing each large repository, its size, and the peak operations per second you observed. Confirm with the GitLab documentation for your chosen version which repository metrics it exposes so the baseline can be compared later.

  2. Measure CI concurrency and job profile

    Your CI owners count the number of pipelines and jobs that run at the same time at peak, how long clone and fetch steps take inside jobs, and which pipelines clone the full history. Shallow clone settings and monorepo-aware pipelines change this load, so record them alongside the numbers. The output is a concurrency figure per hour and a list of pipelines responsible for most Gitaly reads. If your organization has no historical data, say so and plan a measurement window before sizing rather than assuming a profile.

  3. Map the workload to a reference architecture

    Your architects compare the inventory and the peak API request rate with GitLab's published reference architectures, which are sized by users and requests per second rather than headcount alone. Monorepo size and CI load can push a team to a larger tier than its user count suggests, so note that adjustment explicitly. The check is a written decision naming the reference architecture, the install method and the reason for any upward adjustment. Confirm the RPS targets and the recommended high availability strategy in the GitLab reference architectures documentation for your version before you commit.

  4. Provision Gitaly and supporting nodes at a starting size

    Your infrastructure team builds the environment at the larger starting size the mapping suggests, with dedicated Gitaly storage that has enough disk throughput and memory for large repositories, plus Sidekiq and Rails capacity sized for the CI load. Keep the first build simple so that each node role is visible when you measure it. The step is complete when every node passes health checks and the configuration is recorded in version control. Whether Gitaly Cluster or sharded Gitaly fits your repository-level HA needs is a separate decision, so confirm its current limitations in the GitLab documentation before you finalize the layout.

  5. Run load tests with the GitLab Performance Tool

    A performance engineer runs the GitLab Performance Tool against the new environment, using a request mix that reflects the Git operations and API calls measured in the first two steps. Include your largest repositories and a CI-like concurrency pattern so that Gitaly and Sidekiq are exercised together. The output is a results report compared with the request rate and latency targets for the chosen reference architecture. If results miss the targets, fix the bottleneck and rerun rather than accepting the size. Confirm the tool's current version, supported test setup and result interpretation in the GitLab documentation.

  6. Monitor Gitaly and Sidekiq queues in production

    After go-live, your operations team watches Gitaly latency and error signals, repository storage utilization, and Sidekiq queue depth and job latency through the Prometheus metrics that GitLab exposes. Set alert thresholds based on the load test baseline, not on generic values. The check is a dashboard and alert set in place for at least one full peak cycle, with a documented review owner. Confirm the metric names and monitoring setup for your version in the GitLab monitoring documentation, since they change between releases.

  7. Scale down only after sustained evidence

    Your capacity owner considers reducing node sizes only after production data shows headroom across several peak cycles, including the month-end and release windows identified in the first step. Make one change at a time, rerun the load test after each change, and keep the previous configuration available for a rollback. The step is done when the reduced size passes the load test, production metrics stay within the agreed thresholds, and the decision is recorded with the evidence. Starting large and reducing later is safer than the reverse, because a shortfall during a release is harder to recover from than an extra node in the bill.

Security and operational considerations for large repositories

Large monorepos and heavy CI concentrate risk in a few places: the runners that execute untrusted jobs, the Gitaly data that holds every repository, and the upgrade and maintenance windows that touch the whole instance. The cards below are the checks to settle alongside sizing, not after go-live.

Isolate runners from sensitive repositories

Runners execute whatever jobs their projects send them, so a runner that serves a monorepo with broad access can also reach secrets and code it should not. Plan separate runner fleets or tagged pools for sensitive projects, and decide which executor each pool uses before scaling CI concurrency. Ask your partner or team to confirm how runner isolation, registration tokens and job networking will be enforced in your environment, using the GitLab Runner documentation as the reference.

Confirm Gitaly backup coverage

Gitaly holds the repository data that grows with a monorepo, and backup coverage at that size is easy to assume rather than verify. Confirm in the backup and restore documentation which Gitaly data the backup task captures, how long a full restore takes at your repository size, and whether your storage layer offers snapshots. Gitaly Cluster does not offer snapshot backups, so the restore procedure must be tested end to end.

Plan for upgrade stops on large instances

GitLab requires upgrades to pass through required upgrade stops, and on a large instance each stop adds migration time, background job drain and a longer rollback window. Map your current version against the stops before scheduling work, and ask whether your topology supports the zero-downtime procedure for each step. Budget test upgrades on a copy of production data, since migration duration on a monorepo-heavy database is the main unknown.

Monitor and schedule maintenance windows

Heavy CI concurrency hides saturation: queues grow, Gitaly latency rises and Sidekiq backs up before anyone sees an outage. Define the health checks, Prometheus metrics and log sources you will watch for Gitaly, Sidekiq and the runner fleet, and set alert thresholds from your own baseline. Agree maintenance windows with CI teams in advance, because any restart or upgrade stops pipelines across every monorepo project at once.

Roll out hardening gradually

GitLab's hardening guidance covers application settings, CI/CD, gitlab.rb, the operating system and NIST SP 800-53 alignment, and GitLab describes it as a work in progress to be rolled out gradually. Treat each control as a change with its own test, owner and rollback. Record which settings you adopted, which you deferred and why, so the evidence matches what runs in production when an assessor or internal auditor asks.

Questions teams ask before scaling GitLab for monorepos

How much does it cost to scale self-managed GitLab for a large monorepo?

Cost has three components: infrastructure, licensing and implementation effort. Infrastructure is the compute, memory, storage and network your cloud account or data center bills, and it recurs every month. Licensing depends on the tier you choose: the GitLab pricing page lists GitLab Free at 0 US dollars, Premium at 29 US dollars per user per month billed annually, and Ultimate as custom priced, with all three available for self-managed installations. Implementation effort is usually one-time, covering sizing, build, load testing and cutover. Ask any partner for a quote that separates these lines, states which tier is assumed, and lists the recurring infrastructure items the estimate excludes, such as storage growth and runner capacity.

How long does sizing and validating a monorepo deployment take?

The duration depends on how much measured data exists before work starts. The main drivers are the size and shape of the largest repositories, how many CI jobs run at peak, whether you already have a reference architecture running, how many environments need validation, and how quickly your change windows and approvals move. Teams with clean metrics from Gitaly, Sidekiq and their CI system usually move faster than teams who must first instrument their systems. Load testing adds time because each test run needs a stable environment and a review of results. Ask for a timeline built from these steps in the written scope, not a generic number.

Can our own team size and validate a monorepo GitLab deployment without a partner?

Yes, many teams do, provided they have engineers who understand Linux administration, PostgreSQL, Redis, Gitaly storage behavior and CI runner design. They also need a way to generate realistic load. GitLab publishes reference architectures with request-per-second targets, and the GitLab Performance Tool can test an environment against those targets before go-live. Your team should be able to read the results, find the bottleneck, and change configuration with a rollback plan. If any of these skills are thin, a partner can cover the gaps, but the decision should rest on the skills you have today and the change windows you can protect.

Should we start with a large GitLab architecture and scale down later?

Starting larger can reduce the risk of a painful resize during a busy period, but it raises recurring infrastructure cost and can leave capacity idle. Starting smaller is cheaper at first but requires a tested path to add nodes, rebalance repositories and move stateful services without long outages. The right choice depends on how fast your monorepos and CI concurrency are growing and how much headroom you can pay for. A common approach is to size against measured peak load, document the scale-up steps in advance, and run a load test at the planned size before committing to a smaller footprint.

Is Gitaly Cluster required for a large monorepo?

No. Gitaly Cluster with Praefect is one option for repository-level high availability, and the GitLab reference architectures generally recommend a high availability strategy at 3,000 or more users. That recommendation is about availability, not repository size alone. Sharded Gitaly is an alternative that spreads repositories across nodes. Whichever you choose, large repositories need fast disks, enough memory for Git operations and careful monitoring of repository growth. Confirm current Gitaly Cluster limitations with GitLab before choosing it, since the documentation covers backup behavior and other constraints that affect the design.

What do we need to provide so a partner can size a monorepo deployment?

Provide repository metrics, CI data and operational constraints. For repositories, that means the size of the largest repositories, total storage, growth over recent months, the count of branches and tags, and typical clone and fetch frequency. For CI, provide job volume by hour, peak concurrency, average and longest job durations, the executors in use and the largest pipelines. You should also share current user counts, API request patterns if known, existing monitoring data, backup and recovery targets, and the change windows available for cutover and load testing. Missing data is normal, but the quote should say which assumptions were made.

What should a written quote for monorepo scaling include?

A useful quote lists the scope in numbered deliverables: current-state review, target reference architecture, infrastructure design, configuration of Gitaly, PostgreSQL, Redis, Sidekiq and runners, load testing against stated targets, cutover support, and documentation. It should name the GitLab tier and version assumed, state which environments are covered, and identify what the client provides, including data, access and change windows. It should separate one-time implementation fees from recurring items such as retainers or support. Finally, it should state exclusions, such as cloud spend, licensing your organization buys directly from GitLab, and any work not reflected in the agreed deliverables.

How DeployOpen scopes and supports GitLab sizing work

DeployOpen plans, implements, tests, hardens and supports self-managed GitLab inside your own infrastructure, whether that is your cloud accounts, your data centers or an air-gapped network. For sizing work on large monorepos, that means we start from your measured repository sizes, CI concurrency and request patterns, then map them to a reference architecture and a Gitaly layout before any hardware or cloud resources are ordered. Most engagements are fixed-scope, with the scope, deliverables and timelines agreed in writing before work starts. The written scope should name the environments covered, the load test targets, the documents handed over and the items the client must provide, such as access, network diagrams and current repository statistics.

Pricing follows from that written scope. DeployOpen does not publish a price list, so the quote reflects the components in scope, the number of environments, and how much validation the client wants. When you request a quote, ask the vendor-independent questions that drive cost: how many environments must be sized (production, staging, disaster recovery), whether load testing is included and against which targets, whether the team needs knowledge transfer, and which recurring items are excluded. Ask for each item to be marked as one-time or recurring so the total cost of ownership is visible. Confirm current GitLab license tier requirements directly with GitLab's pricing page because feature availability affects scope.

Ongoing support is available as a retainer for the period after go-live. In practice this covers monitoring review, reviewing Gitaly and runner capacity as monorepo growth continues, planning upgrades through required upgrade stops, and re-running performance checks after significant changes. Agree in writing what the retainer includes, how requests are prioritized, and whether scaling changes are covered or billed separately. DeployOpen does not issue audit reports, attestations or certifications. If your organization needs independent assurance of its GitLab environment, that evidence comes from an independent auditor or certification body, and our role is to prepare the systems, configuration and records they will review.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.