YouTube Summaries

← All summaries

Hosting Git at scale: packfiles, Spokes, and a write-ahead log

2026-08-28 Fri ⏱ 12 min theprimeagen

A walk-through of Vincent's Cursor blog post on why hosting Git is hard. The short answer is packfiles: they force the server and client to speak in whole-object bundles, which defeats key-value stores and distributed filesystems alike. The industry settled on GitHub's Spokes (three-phase commit across replicas), which makes reads fast and writes progressively slower as a repo gets popular. Cursor's answer is to put a write-ahead log on S3 and drop consensus entirely.

Git's object model, briefly

A commit is a pointer to a tree; a tree points to other trees and blobs; a tree is a directory and a blob is a file. Commits, trees, and blobs are all "objects", and a bundle of them is a packfile. To find the contents of one file at one commit you must walk from the commit root down through subdirectories to the blob - there is no direct index.

Crucially, the wire protocol is packfiles in both directions: fetch, push, and pull all move packfiles between client and server. That is what makes Git hard to host.

Why the obvious approaches fail

  • Key-value store :: every object has a unique SHA, so SHA -> object looks natural. But answering anything about a commit means thousands of round trips as the repo grows. Google built this, tried to make it fast, and abandoned it because clone was far too slow.
  • Distributed filesystem :: GitHub tried it and abandoned it too - again, packfiles.

What you actually want is the repo on many disks across many machines, so one outage does not lose it and heavy read traffic (mostly CI) does not saturate a single box.

Spokes and the tail-at-scale problem

GitHub built Spokes around 2013 and it became the industry standard - most hosts run a variant. It does not distribute Git itself; it works at the packfile level, storing real Git repositories on local NVMe and replicating them while keeping copies in sync. A minimum of three machines hold each repo, a routing table in a database says where they are, and any read can go to any replica. Popular repos get more replicas.

Writes use a three-phase commit: send the packfile, prepare (can you store this?), lock the replicas that said yes, then commit to finalize. That is four requests per node, and each extra request raises the odds of hitting a slow tail. The arithmetic is simply 1 minus the percentile raised to the number of requests: five nodes means 20 requests, an 18.2% chance of a p99 stall somewhere in the chain. For something like the DeepSeek repo, with many replicas, you could be making 200 requests per commit - roughly 86% of writes hit a bad tail. Reads are fast, writes get worse the more popular a repository becomes.

Cursor's approach: a write-ahead log on S3

Instead of replicating repositories, store the sequence of write operations - a write-ahead log, the same idea Postgres and SQLite use - in S3. Appending is trivial, and any server can reconstruct the repository state by reading the log.

Consequences:

  • No consensus, no voting, no primary node.
  • No standing replicas. The 25 million repos created each month do not each need three machines; they can need zero, because the state lives in S3 and restores in milliseconds.
  • Rendezvous hashing picks which node serves a given repo, so the same repo consistently lands on the same server rather than every node restoring from the log.
  • Compaction keeps the log tight by rolling many packfiles into one - Prime notes he did not know Git had compaction either.

With fast NVMe in front of S3 they report around 16,000 commits per minute.

The blog post has the technical detail; the video's own conclusion is mostly the engineer's eternal delusion - "actually, I could build that."