R001 · Infrastructure for agents at scale › Developer infrastructure under agent load

Scaling Git at OpenAI (Pando)

Read the original

dev-infragitmonorepoagents-at-scaledistributed-systemsformal-verificationai-built-software

TL;DR

OpenAI replaced its monorepo Git host with Pando, a Git-compatible Rust backend, after Codex multiplied parallel pushes and fetches. Median push latency fell nearly 80% (about 5x) and it now serves nearly 1 PB of Git data per day. The core ideas: store each push as an immutable pack in blob storage, coordinate refs per branch (causal consistency) instead of per repository, and answer fetches by reusing stored packs, delivered as packfile URIs from regional caches.

Source: Scaling Git at OpenAI by Aaron Friel, Taylor Blau and Ted Nyman, published 2026-11-02. Checked against the original article on 2026-11-03. All performance figures are OpenAI's own, not independently reproduced.

The problem

Codex let each engineer run far more work in parallel, which changed the shape of the load as well as its size. From around the end of 2025 the old system struggled.

They decided the limit was how they served the monorepo, not Git itself. They kept Git for its ecosystem, so the stock client and protocol stay unchanged and client fixes can go upstream.

Designs they rejected:

Both fail because they keep two assumptions: one consistent snapshot of all refs, and a unique pack built for each client. Pando drops both.

Architecture

Pushes append a pack; fetches are served from cached packsGit clientsengineers, agents, CIPando server (Rust)negotiation, ref updatesMetadata storeref version per branchExpress cachespack bytes over HTTPBlob storeone immutable pack per pushCompactionmerges small packs (LSM)push, fetchpack URIsper-ref CASwrite packdownload packsfillmerge
Pando write and read paths · 6 components

Write path. A push streams into blob storage as one immutable pack and is validated in a single pass, without being unpacked into a local repository. One multi-key transaction then writes a "ref version" (new tip, the pack that supplied it, the earlier ref versions it depends on) and moves the ref pointer, which gives read-your-own-write. The ref pointer is the only contended key, guarded by a CAS-like atomic operation. Metadata work is O(1) per push, even for very large pushes, because only some commits are recorded synchronously.

Read path. Pando maps the client's haves and wants to ref versions using commit mappings recorded at push time, then picks the stored packs that cover the gap. This takes O(log Δ) metadata reads, where Δ is the ref-version distance. It replies with an empty inline pack plus packfile URIs, and the client downloads the packs from Express, a regional pack cache routed by consistent hashing (over 99% hit rate). A separate cache sits in front of the metadata store.

Compaction. Each push makes an L0 pack. Background workers group packs into "covers" over runs of ref versions that grow geometrically (the monorepo reaches L4), and repack a full cover into one better-compressed pack. Covers double as a skip list, which is what makes pack selection logarithmic. Packs at every level are kept and served; none are garbage-collected.

Pando servers never apply packs or repack, so they mostly negotiate and select packs on commodity hardware. Scaling out means adding Pando servers and growing the metadata and blob stores alongside them.

Bottlenecks and how each was handled

BottleneckWhat Pando doesReported result
One coordination point (a repo-wide snapshot) serializes unrelated pushesCausal consistency: per-ref versions, CAS on the ref pointer only, O(1) metadata per pushMedian push latency down nearly 80%; "many thousands" of concurrent pushers without slowdown
Building a unique pack per client on fetchReuse stored packs and return them as packfile URIs57 TB served in one peak hour, over 99% of bytes from local disk cache
Ref advertisement over 100 MiB with millions of branchesAdvertise only a chosen subset; new feature branches see only trunkAdvertisement size stays flat as branches grow
Pushed packs that can't be reused by other readersPack depends only on what the server advertised, so anyone holding trunk fetches the branch in one packMedian pushed pack under 20 KiB, p99 under 3 MiB
Tens of thousands of small packs a day to catch up on trunkLSM-style compaction into geometric covers (L0 to L4); covers act as a skip listPack selection is O(log Δ) in the version gap
Replicas applying and repacking every pushServers never unpack or repack; they only negotiate and select packsAbout 1 PB/day on "a handful of CPU cores"
Delivering bytes to many regionsExpress regional caches with consistent hashing; separate metadata cacheClones and fetches saturate 10 Gbps links on standard cloud VMs
Client edge cases with reused packs (concurrent downloads, interrupted or resumed transfers)Fixes sent upstream; parallel download and indexing of independent packs; tracing and byte counts for packfile-uriSeveral changes already in upstream Git
--force-with-lease needs the branch tip, but the pack should be built against trunk only"Explicit haves": the server advertises the branch tip separately from the history the pusher may omitLease check and reusable trunk-based packs both work

Tradeoffs

The central bet is giving up a repository-wide snapshot to get independent, parallel branch updates.

How it was built, verified and rolled out

One engineer owned the core design, Codex agents wrote most of the implementation, and a handful of engineers deployed it. It went from kickoff to production in about 10 weeks and has carried production traffic since April 2026. It is a greenfield Rust codebase with no legacy dependencies.

Because agents wrote the code, correctness rested on layered checks rather than review alone:

Rollout without downtime. Pando first ran as a read- and write-through proxy in front of the old backend, keeping both in sync. It deduplicated and combined requests before proxying, which made the old system healthier during the move. Clients moved in phases through an internal wrapper around the Git CLI, and OpenAI migrated hundreds of integrations that used legacy APIs, webhooks and repository downloads. Codex skills let developers ask Codex to migrate their own checkouts and services.

OpenAI is sending client fixes upstream and exploring ways to share Pando, including for many agents collaborating on one repository. No product or open-source release is announced.

Reusable lessons

  1. Plan for agent fan-out. One push becomes several CI and agent fetches of the same commit. Size the read path for the write rate times the fan-out, not for human traffic.

  2. Question the guarantees, not just the implementation. 3PC and a shared WAL both failed because they kept a repo-wide snapshot. Most workflows only need ordering per branch, and narrowing the guarantee removed the bottleneck.

  3. Shrink the contended state to one key. Make writes immutable appends, flip a single pointer with CAS, and push everything else (compaction scheduling, extra commit mappings) to async work.

  4. Separate negotiation from byte delivery. Keep the protocol exchange small and move bulk bytes over plain HTTP so regional caches can carry them.

  5. Serve reusable artifacts, not bespoke responses. Accepting some redundant bytes in exchange for cache hits and near-zero server CPU was the winning trade.

  6. Control what clients may omit. Advertising only trunk made every pushed pack reusable by any reader. What a server advertises shapes what it can cache.

  7. Stay protocol-compatible and fix the client upstream. Zero workflow change made adoption possible; the client patches unlocked the last gains.

  8. Migrate behind a proxy. A read- and write-through proxy in front of the old system allowed a no-downtime cutover and relieved the old system while it lasted.

  9. When agents write the code, invest in verification. Conformance suites, deterministic simulation and formal specs made a 10-week rewrite of critical infrastructure safe to ship.

  10. Instrument the phases. OpenAI added tracing to tell pack generation from transfer time. Negotiation, transfer, indexing and checkout are separate costs, and a median hides the tail.

Open questions

Sources

Connections

See R001 on the knowledge map

Part of the Research notes on nowucca.com. Figures and claims are the source's own unless the summary says otherwise.