Architecture
Each repository is a write-ahead log in the bucket; every instance is a cache or a reader of that log.
The bucket layout
Logs, packs and checkpoints are immutable. Nothing is visible before the manifest's compare-and-swap.
- manifest.pb
Tiny, CAS-rewritten:
head_seq, the live pack set, log segments, the checkpoint pointer. The linearization point.- log/<first_seq>.pb
Immutable PUSH, REF_UPDATE and COMPACT entries. One small object per publish batch.
- wal/<checksum>.pack/.idx/.rev/.bitmap/.commit-graph
Immutable packs, content-addressed by pack checksum, plus the side-files a reader needs.
- checkpoints/<seq>/
Folded state at
seq: live pack set and fullRefSnapshot.- leases/<name>.pb
CAS lease with TTL heartbeat. The only cross-instance mutex.
- cache/api/v1/, cache/archive/v1/
Shared cache of immutable API answers and archives.
- lfs/objects/<aa>/<bb>/<oid>
LFS objects, sha256-addressed and immutable.
Write path
A push is acknowledged only after the bucket acknowledged it. Concurrent writers race on one CAS.
A ref that moved meanwhile is answered ng. Concurrent pushes on one instance share one CAS within wal.batch_window (default 5ms) per repository.
Read path
Every read starts with a conditional GET of the manifest, so every instance is as fresh as a fetch.
| Sync level | Brings | Used by |
|---|---|---|
| Refs | Checkpoint RefSnapshotand every log entry's ref transaction. No packs. | info/refs, ls-refs, API refs, resolve and overview |
| Full | Refs and every live pack, downloaded locally in parallel stripes | upload-pack, receive-pack, API object endpoints, compaction |
Checkpoints and compaction
A checkpoint folds the log, so a cold start reads a snapshot and the tail, never the whole log. Compaction folds fresh packs geometrically under a lease, and needs at least two of them.
| Key | Fires when | Default |
|---|---|---|
wal.snapshot_every_entries | This many log entries since the last checkpoint | 256 |
wal.checkpoint_interval | The last checkpoint is this old | 1h |
wal.checkpoint_tail_bytes | The log tail after it exceeds this | 8MiB |
compaction.trigger_packs | This many tier-0 packs exist | 16 |
compaction.trigger_bytes | Tier-0 pack bytes exceed this | 1GiB |
compaction.retention_superseded | Superseded packs, folded logs and old checkpoints are kept this long before bucket GC | 7d |
The maintainer
A push leaves a marker; the maintainer visits only marked repositories and does one bounded unit of the most important missing work at a time.
Everything it produces is a pure function of config and WAL state, so a deleted artefact is rebuilt identically. A repository nobody pushes to is never visited; Cost model has the numbers.
Recovery
Disk and memory are caches. Wipe every instance and you lose only warmth.
Packs download on the first object request.