Over the past twelve months, as Git traffic surged exponentially, GitHub began maintaining copies of 99.99999% of its repositories simultaneously in both its own data centers and on Azure. The final 0.00001%—the platform's most active repositories—remain constrained by a single obstacle: a 25-millisecond round-trip latency between regions.
The migration strategy rests on two core architectural principles: reducing the need for coordination between systems, and separating storage infrastructure from compute resources. GitHub's approach bridges its legacy design with a new infrastructure capable of handling agent-scale workloads.
Migration timeline and constraints
The scope and pace of the transition were shaped by the rapid rise of agentic workloads: traffic expanding at an accelerating rate, physical power limitations in GitHub's own data centers and their surrounding region, and supply chain delays affecting hardware procurement. At the start of the migration, available capacity—even with maximum expansion—provided only enough runway to move safely, not slowly.
Although GitHub had tested new architectural models for scaling Git on cloud platforms, attempting to change both storage architecture and hosting infrastructure simultaneously under such growth posed unacceptable risk. Given the service's scale and importance to the developer community, the work required careful sequencing: transfer the data first, then refactor the architecture once it had arrived.
Git operations represent a Tier 0 service—a foundational capability on which nearly all other GitHub functions depend. This criticality meant that data, services, and their dependencies had to migrate as a unit. The first repository copy landed in Azure's Central US region in August 2025. Currently, most repositories maintain two of their five replicas in Azure, and Azure now handles roughly half of all Git traffic. Throughout this period, Azure absorbed the platform's growth while GitHub's own data centers remained relatively flat.
Traffic routing follows data placement. Most repositories maintain five replicas to balance durability, availability, and capacity. To reduce read latency, Spokes—GitHub's quorum coordinator—uses preferential routing to direct requests to a replica in the same region and availability zone. As replicas migrate to Azure, the proportion of traffic served from Azure increases incrementally until the final replica arrives and the old region stops receiving requests. Every repository undergoes this staged transition.
Per-reference quorums unlock the final repositories
The remaining 0.00001% of repositories face a throughput bottleneck rooted in GitHub's current architecture. When a repository spans multiple regions, Spokes' quorum requires only a majority of replicas to acknowledge a write, but it waits for every healthy replica to respond (up to a timeout) before proceeding. This means the slowest healthy replica determines the latency of every write. Since each write holds a repository-wide lock until it commits, the slowest replica also sets the repository's write throughput ceiling. Once a replica resides in Azure—roughly 1,000 miles from GitHub's data centers—each network round trip takes approximately 25 milliseconds. A repository already near its throughput limit cannot absorb multiple round trips per write; it would fall further behind with each push.
This is where minimizing coordination becomes critical. Specifically: avoid serializing operations that do not require it. Git's consistency model applies to each reference individually. Once the server accepts an update to a reference, clients must never see an older value—only that value or a newer one. This holds for fast-forwards, force pushes, and deletes alike. However, updates to different references typically have no dependencies on each other and can execute independently.
GitHub is shifting the quorum's scope from the entire repository to individual references. Holding a repository-wide lock through all reference updates and network round trips converts the quorum into a single, unordered queue with one write in flight at a time. Each write waits as long as the slowest healthy replica takes. As write rate increases, the queue grows, and each write waits longer than its predecessor.
Per-reference serialization means only writes contending on the same reference must wait for each other. In practice, most repository writes target different references—agents and developers pushing to their own branches, for instance—so they no longer block one another. Individual writes still experience cross-region latency, but writes to different references can be in flight simultaneously. This eliminates the single repository-level bottleneck. Comparing the two approaches under similar load reveals how queueing and timeouts accumulate differently.
These changes raise a repository's write throughput ceiling roughly proportionally to the number of references being written concurrently, and enable the final repositories to move to Azure. Internal testing with production-like traffic showed writes to different references consistently achieved 3–4x higher throughput at lower latency.
Decoupling reads from writes through object storage
Most repositories exhibit heavy read skew, with between 100 and 1,000 reads for every write. Currently, reads and writes target the same replicas, forcing them to compete for identical resources and preventing independent scaling.
Separating storage from compute changes this dynamic. Once repository data is durably stored in Azure Blob Storage and updated with each incoming write, read traffic can be decoupled from the write quorum, and compute resources can be scaled independently for each workload. For example, reads would benefit from far more in-memory cache than currently allocated, but that memory is also required for compaction. Once separated, each workload receives its own tuned configuration.
The first step involves making object storage a member of the quorum as a special participant called a virtual replica. The compute representing it is GitHub's first fully ephemeral node. It bridges to object storage, streaming incoming writes and serving no reads. As a quorum member, a write is not acknowledged until it is durable in object storage.
This adds modest latency to each write, but per-reference serialization prevents it from becoming a throughput constraint, just as it does with cross-region round trips. The virtual write replica also coalesces transactions on disjoint references into a single set of network I/Os to object storage, so a busy repository pays for one round trip across many concurrent writes instead of one per write. Currently, the virtual write replica also handles compaction, and read replicas inherit the compacted state.
With the virtual write replica in place, GitHub can scale out as many virtual read replicas as a repository requires, on demand. Each read replica warms its cache from Azure Blob Storage and begins accepting read traffic without joining the quorum, using object storage as the source of truth and reconciling its local state against it in the background.
This step unlocks substantial read scaling. Internal testing showed GitHub's distributed load testing harness routinely hit ceilings in the current architecture. Against virtual read replicas, the harness exhausted its own limits first. However, this approach introduces challenges addressed in subsequent iterations:
- Virtual read replicas begin by reconciling with object storage in the background, making them suitable for some read workloads but not all. Serving every read type requires moving that reconciliation inline, fetching only the reference state and data that changed since the replica last caught up.
- While per-reference serialization has incrementally raised write throughput, the quorum remains the limiting factor for further increases.
The path forward
GitHub's current infrastructure was constructed around the Spokes quorum, which has evolved into far more than a coordination mechanism. It now functions as an intelligent routing and load balancing layer, a unified API that internal systems use to access and transact repository data at over 100 billion operations per day, and a suite of background systems called "sweepers" that manage repository placement, repair, and rebalancing across storage nodes.
The vast majority of capabilities within the Spokes service umbrella apply equally to the new architecture as to the existing one. However, GitHub acknowledges that the commit protocol that scaled the platform to a billion repositories will not scale it to the next billion and beyond.
With these steps in place, the next constraint is write throughput. Every write still waits on replicas holding a full repository copy, yet very little of a write actually requires ordering. Git objects are immutable and identified by their contents, so they can be stored without consensus. What remains is small but difficult: ordering it as rapidly as possible without moving the bottleneck elsewhere. Designing this on a whiteboard differs fundamentally from implementing it beneath a billion repositories that developers and agents write to continuously. Reaching this goal required rethinking second-order effects, including where durable reference state resides and how compaction and garbage collection scale.
Agent traffic continues accelerating, and each of these steps provides repositories additional capacity as it lands, without requiring the final architecture to be complete.
GitHub plans to present the end state architecture next week at GitHub Universe and in the final post of this series, detailing what it delivers for write throughput, the second-order problems that required solving, and why a (small) consensus group still exists somewhere in the stack.