GitFarm: Git® as a Service for Large-Scale Monorepos
Staff Engineer
Senior Software Engineer
Senior Software Engineer
Introduction
At Uber’s monorepo scale, traditional Git® workflows have become a fundamental bottleneck. Cloning multi-gigabyte repositories, maintaining local checkouts, periodically syncing from upstream, and executing repetitive fetch or push operations consume substantial compute and I/O across hundreds of automation systems. While CI systems such as Jenkins® and Buildkite® provide caching mechanisms to reduce clone times, in practice, these approaches incur significant infrastructure overhead, manual maintenance, and cold-start latencies of several minutes for large monorepos. Moreover, thousands of independent clone and fetch operations impose heavy loads on upstream Git servers, making them a shared scalability bottleneck.
To address this, we built GitFarm—a platform that provides Git as a Service through a high-performance gRPC® API. GitFarm isn’t a Git SCM—it doesn’t store, replicate, or serve repositories. Instead, it acts as a centralized Git client in the cloud: it executes standard Git commands on behalf of other services, within secure, ephemeral sandboxes backed by pre-warmed repository and container pools. The system enforces identity-scoped authorization, supports multi-command workflows, and leverages specialized back-end clusters for workload isolation.
For clients, this means no local clones, access to a full Git checkout in under 500 milliseconds, and significantly lower compute and I/O overhead. Services no longer suffer cold starts of 10-15 minutes due to initial clones on each host. In production, GitFarm has reduced client-side resource utilization by over 80% while preserving the flexibility of native Git semantics.
Background
At Uber, various automation systems and developer services invoke Git millions of times per day across multiple monorepos spanning Go, Java, Python, Web, Android, and iOS. Historically, each system maintained its own full repository checkout—even for lightweight operations like reading files or validating merges. This duplication consumed large amounts of compute and storage, and generated sustained loads on upstream Git servers as every system performed its own clone and fetch operations.
The Cost of Local Checkouts
Cloning Uber’s Go monorepo takes roughly 15 minutes and consumes around 6 CPU cores, 32 GB of memory, and over 40 GB of disk. A service that clones all major monorepos can easily require 16 CPU cores, 64 GB of memory, and 96 GB of storage—just to maintain repository state.
Techniques like shallow clones, partial clones, or single-branch clones reduce initial data transfer, but don’t address the fundamental problem: each request still forces the upstream Git server to enumerate objects, generate packfiles, and stream data. As the client count grows, this turns the Git server into a shared bottleneck. These optimizations also have functional limitations—operations like merge-base or bisect may fail on shallow clones.
Why Not Just Use CI?
A natural alternative is to offload Git operations to CI platforms like Jenkins or Buildkite. Both provide standardized execution environments and handle repository checkouts as part of job execution. But this model has significant drawbacks at Uber’s scale:
- Heavyweight for simple operations. Need to compute a merge-base and push a ref? With CI, you’re provisioning a worker, initializing a workspace, and syncing a repository—all for a few Git commands.
- No standalone Git API. All interactions must occur within the job. You can’t just call an API to run git log, you need a full build job.
- Redundant work. Even when multiple jobs target the same commit, each agent fetches independently.
- Stale state. Long-lived agents accumulate outdated refs and packfiles, degrading performance over time.
- Coupled to build a lifecycle. Repository operations can’t be triggered outside of a running job — no pre-warming, no async maintenance, no programmatic access.
These limitations motivated GitFarm: a shared, service-based alternative purpose-built for executing Git operations efficiently at scale.
Architecture
When a request is submitted to GitFarm, it’s first received by the GitFarm Gateway, which forwards the request to the GitFarm Backend. Within the Backend, an available node is chosen to process the request. The request then executes in a sandbox on that node, where a pre-warmed repository checkout is mounted, as shown in Figure 1.
Figure 1: GitFarm architecture.
Gateway–Entrypoint
The Gateway is responsible for authenticating and authorizing incoming requests, and routing them to the appropriate back end. Upon receiving a request, the Gateway identifies the client and verifies that the client has permission to access the requested repository. Requests from clients lacking the required privileges are denied.
The Gateway also functions as a load balancer for the GitFarm back ends. It continuously tracks back-end node availability by monitoring periodic heartbeats and status updates that report the number of available sandboxes on each node for each repository. This state is maintained in a Redis® data store. For each incoming request, the Gateway selects the back-end node with the highest number of available repository checkouts for the requested repository, and marks the selected repository checkout as occupied. It then releases the sandbox upon completion by updating the Redis state. If no back-end nodes are available for a given repository, the Gateway rejects incoming requests, effectively throttling the workload due to insufficient resources.
Backend–Request Processor
The GitFarm Backend forms the core execution layer of the system. It maintains a warm, up-to-date repository state by periodically synchronizing on-disk repositories with their upstream remotes (via git fetch). The Backend manages a pool of isolated execution environments (sandboxes) used to execute Git commands issued through API requests.
For each incoming request, the Backend provisions the appropriate repository state, identity, and execution context, and mounts them into a sandbox to perform the requested operation, ensuring isolation and consistency across executions, as shown in Figure 2.
Figure 2: GitFarm Backend architecture.
Each GitFarm Backend node maintains a single on-disk bare clone for each repository. These clones are kept up to date through an event-driven synchronization strategy (push-based updates) that fetches changes as soon as they become available. We also perform periodic synchronizations with the upstream repository by executing git fetch every 5 minutes, to ensure the repository state remains fresh in the event of missed or delayed events.
GitFarm doesn’t enforce a single global freshness guarantee across all workloads. Instead, it exposes the repository state that’s eventually consistent with the upstream repository, while allowing clients to explicitly control freshness on a per-request basis.
For workloads that require the most up-to-date repository state, clients may invoke an explicit git fetch as part of their execution session before running any other Git commands. This ensures that all subsequent operations within the session observe the latest available commits from the upstream repository. Other workloads that tolerate bounded staleness may rely solely on the Backend’s repository synchronization mechanisms to minimize execution latency and avoid redundant fetches.
Another part of the architecture is sandboxes. A sandbox is an ephemeral execution environment (container) where all Git operations for a given request are performed. Each request runs in complete isolation within its own sandbox and on its own Git checkout, ensuring separation between other requests executing in GitFarm. Sandboxes are pre-initialized to reduce latency, and are protected by strict security boundaries. Access privileges within a sandbox are scoped to the caller’s identity.
Creating a new repository checkout and provisioning a sandbox container on demand for each request is highly resource-intensive. Spinning up a sandbox container typically takes 1-2 seconds, and materializing a repository checkout from a local bare clone (periodically synchronized from upstream) can take up to 3 minutes. Such per-request latencies are unacceptable and don’t scale for high-volume workloads.
To address this, GitFarm employs a pooling model for both repository checkouts and sandbox containers. The Backend maintains a fixed-size pool of repository checkouts on disk, each synchronized from a local bare clone of the repository. These pre-warmed checkouts are immediately available for request execution.
Similarly, the Backend pre-creates a fixed-size pool of sandbox containers, each initialized with an isolated execution environment and a dedicated mount point. When a request arrives, the Backend acquires an available sandbox from the pool and mounts a repository checkout from the repository pool into the sandbox. This design eliminates on-demand provisioning and allows multiple repositories to be efficiently served within a single cluster.
With pooling in place, the overhead of providing a sandbox with a ready-to-use repository checkout is reduced to less than a second (as seen in Figure 3), substantially lowering request latency. This optimization enables the system to dedicate resources to executing Git operations rather than incurring repeated initialization costs associated with cold starts.
Figure 3: P95 Latency to acquire sandbox across Uber monorepos.
Request Chaining
Many automation workflows require executing multiple Git operations sequentially, where the output of one command is consumed by subsequent commands, all operating within the same repository checkout. For example, computing the merge base between 2 branches and publishing it under a derived reference requires capturing the output of git merge-base and using it to push a new Git ref.
GitFarm supports such workflows through a bidirectional gRPC streaming API that allows clients to execute a sequence of Git commands within a single persistent session, with full access to stdin and stdout. This model preserves a consistent repository checkout across commands while enabling output-dependent command chaining, minimizing connection setup and environment initialization overhead.
Clustering
Clustering in GitFarm refers to deploying multiple GitFarm Backend nodes grouped into logical clusters, each purpose-built to serve a specific, uniform use case, as shown in Figure 4. This model ensures predictable performance characteristics while avoiding noisy neighbor effects caused by heterogeneous workloads sharing the same back-end nodes.
At Uber, we operate multiple specialized clusters in addition to a generic shared cluster. Specialized clusters are tailored for high-throughput or latency-sensitive workloads with well-defined access patterns, whereas the shared cluster supports lighter-weight use cases and provides a fast, low-friction integration path for new clients, while isolating heterogeneous workloads using cluster-level resource partitioning strategies.
When a new use case arises, we conduct a review to determine whether the workload can be safely accommodated by an existing cluster or requires a dedicated one. For use cases that warrant isolation, we perform sizing analysis and apply cluster-specific configuration updates (like resource limits, sandbox pool sizing, synchronization policies) prior to onboarding.
Routing decisions are enforced by the GitFarm Gateway, which selects the appropriate cluster for each incoming request based on centrally-managed placement policies. These policies associate each client with a designated cluster, enabling fast and deterministic request routing while preserving workload isolation. This design allows GitFarm to support specialized clusters alongside a shared cluster, without exposing complexity to clients.
Figure 4: GitFarm clustering setup.
API Specification
GitFarm exposes an execution interface (Figure 5) that enables clients to execute a sequence of Git commands within a single repository checkout. The interface is designed to support multi-step workflows while preserving repository consistency and minimizing execution overhead.
Figure 5: Pseudo interface for the GitFarm API.
Each Exec invocation establishes a persistent session bound to a single logical repository checkout. Commands are executed sequentially in the order they are received, and the result of each command is returned to the client as a corresponding CommandResult. The alias field is used to correlate command invocations with their outputs.
GitFarm provides the following guarantees for each execution session:
- Isolation: commands execute within an isolated sandbox environment
- Consistency: all commands observe a consistent repository state throughout the session
- Determinism: command execution order matches the order of submission on the session
Command failures are surfaced via non-zero exit codes and populated standard error output. Fatal errors terminate the session.
Results
GitFarm has been in production at Uber since early 2025. Here’s what we’ve seen across 3 representative workloads.
Reducing 80%+ of Compute for Read-Heavy Services
One of our production services determines code ownership by scanning CODEOWNERS files across hundreds of thousands of directories in Uber’s monorepos. Before GitFarm, it ran on 6 hosts, each maintaining full local checkouts of every monorepo, synced via cron every 15 minutes.
After switching to GitFarm API calls, the service dropped its local checkouts entirely. The impact was dramatic:
- CPU: over 70 cores → 16 cores (77% reduction) as shown in Figure 6
- Memory: 400-600GB → 32 GB (90%+ reduction) as shown in Figure 7
- Startup time: 15-20 minutes → under 1 minute
Beyond raw savings, removing local checkouts eliminated the need for per-instance disk management, repository repair, and bootstrap synchronization. The service now scales independently of monorepo size.
Figure 6: CPU cores usage over time.
Figure 7: Memory usage over time.
Short-Lived Write-Oriented Git Workflows
A production service needs to fetch a branch, compute its merge base against main, and push the result as a new remote ref. With GitFarm, this entire workflow runs within a single execution session: a short sequence of Git commands executed in one sandbox, backed by a warm repository, with no local state required on the client.
The end-to-end p50 latency is about 25 seconds, driven primarily by the Git operations themselves. A git fetch takes roughly 5 seconds, and a git push about 12 seconds. We validated this by comparing against direct Git server interactions, where latencies were nearly identical, confirming that GitFarm introduces minimal overhead.
Without GitFarm, the same workflow would require cloning or syncing the repository on demand, adding minutes of startup time before any Git command can run.
Compliance Auditing for Bypassed Workflows
A compliance service audits commits that bypass standard review checks. It processes 10,000-20,000 events per hour across 9,000 repositories (Uber’s 6 primary monorepos plus thousands of smaller repos). For each flagged commit, it fetches the relevant refs and creates an audit pull request.
Previously, this ran on Buildkite. Each invocation provisioned a worker, set up a workspace, and synced the repository, all before running a few Git commands. The result: p50 latency of 110-160 seconds, dominated by environment setup (as shown in Figure 8).
After switching to GitFarm: p50 latency of 20-30 seconds, an over 80% reduction. The savings come from eliminating 3 layers of overhead: Buildkite agent scheduling, workspace initialization, and per-invocation repository syncing.
Figure 8: P50 execution latency for compliance auditing over a week.
What’s Next?
While the current GitFarm system is robust and capable, several enhancements are planned to improve efficiency and flexibility in handling diverse workloads.
- Streaming Git operation output. Currently, GitFarm returns command results as strings through stdout and stderr. Introducing streaming output would enable real-time feedback for long-running operations and improve responsiveness for interactive use cases.
- Support for alternative repository workspaces. GitFarm currently operates exclusively on full repository checkouts, which can be inefficient for large repositories. Future support for bare clones and sparse checkouts will allow faster, resource-efficient operations when full working trees are unnecessary.
- Extended sessions. The existing gRPC connection is well-suited for short-lived sessions but limited by a 30-minute timeout to avoid resource hogging. But there are use cases where enabling long-lived sessions, lasting hours or even days—would benefit dedicated clusters optimized for persistent, single-use-case workloads that require sustained session continuity.
We’re also planning to onboard additional use cases to GitFarm such as:
- Mirroring changes across Git upstreams. Backup and replication services will leverage GitFarm to continuously monitor repository push events and mirror new commits from a primary Git upstream to a secondary upstream. By centralizing repository state, these services will avoid maintaining local checkouts, while ensuring consistent and up-to-date backups across thousands of repositories.
- Merge to trunk (or main). SubmitQueue (Uber’s merge queue system) will leverage GitFarm to validate incoming changes by applying them onto the latest trunk (e.g. main) branch within sandboxed environments. Validated commits will be pushed under a temporary reference for deferred merging. Once CI validation completes, SubmitQueue will invoke GitFarm to cherry-pick commits from this reference, perform the final merge, and push to trunk. This will enable efficient and isolated merge processing without requiring local repository state.
Conclusion
GitFarm represents a major step forward in how Git operations are executed at Uber’s scale. By providing Git as a Service, it removes the burden of repository management from individual systems, offering a faster, more secure, and scalable alternative to traditional workflows. As the platform evolves with features like streaming output, flexible workspace types, and extended sessions, it’ll continue to enable seamless, high-performance Git operations that keep pace with Uber’s growing monorepos and engineering ecosystem.
Acknowledgments
Cover Photo attributions:
“Git icon” by Jason Long is licensed under CC BY 3.0.
“farm scene” by Christian Collins is licensed under CC BY-SA 2.0.
Android®, Go®, and the Go logos are registered trademarks of Google LLC.
Buildkite is a registered trademark of Buildkite Pty Ltd.
Git and the Git logo are either registered trademarks or trademarks of Software Freedom Conservancy, Inc., corporate home of the Git Project, in the United States and/or other countries.
GitHub is a registered trademark of GitHub, Inc., a subsidiary of Microsoft.
gRPC® is a registered trademark of The Linux Foundation.
IOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license.
Java is a registered trademark of Oracle® and/or its affiliates
Jenkins® is a registered trademark of LF Charities Inc.
Python® and the Python logos are trademarks or registered trademarks of the Python Software Foundation.
Redis is a registered trademark of Redis Ltd. Any rights therein are reserved to Redis Ltd. Any use by Uber is for referential purposes only and does not indicate any sponsorship, endorsement or affiliation between Redis and Uber.
Preetam Dwivedi
Staff Engineer
Preetam Dwivedi is a Staff Engineer on Uber’s Developer Platform team, leading code hosting, review, merge queues, and artifact management. He specializes in distributed systems and scalable developer infrastructure, driving cloud migrations and modernizing engineering workflows and integrations.
Akshay Hacholli
Senior Software Engineer
Akshay Hacholli is a Senior Software Engineer on Uber’s Developer Platform team, where he focuses on building tools that enhance developer productivity across the company.
Adam Bettigole
Senior Software Engineer
Adam Bettigole is a Senior Software Engineer on Uber’s Developer Platform team. He focuses on building scalable, modern, and user-friendly code-review systems for all engineers at Uber.
Products
Company