Terramind Labs

A thousand agents, one branch.

We are designing trellis, source control for AI agents that we plan to release as open source (Apache-2.0), starting from the design Anthropic published in Redesigning source control at Anthropic. Agents all land their work on the same branch, so one database row takes every landing. To check where trellis should keep its records, we measured four databases on that row, on one laptop.

81,318landings a second on one branch, Postgres, 1,000 agents, when one task commits them in batches
38 to 438landings a second in every database we tried when each landing is its own transaction
0.051 vs 4.624 msmedian time of a plain fsync on macOS against a real flush to the drive, in our recorded run
Code and results behind this post
Code

The benchmark

One Rust program that drives all four databases, the script that runs every setting, and the probe that times the two kinds of flush: github.com/terramind-org/science.

public
Results

Every run, one line each

The dataset behind the tables below, the runs we threw away and why, the database settings, and our notes on what happened.

Open →
In short

When many AI agents finish work on the same branch at the same time, they all have to record it in the same place: that branch's row in a database. If each agent records its work separately, they queue for that row, and no database we tried got past 438 a second. If one task collects everything waiting and records it all at once, the same laptop handled 81,318 a second in Postgres. So we have made that a requirement in trellis's design, on Postgres.

Why this project exists

On 13 October 2026 Anthropic described how AI coding agents changed its own source control. In their words: "In May 2026, Anthropic averaged around 2,500 code changes merged per day; as of September, we merged over 30,000 per day." Their main branch's history is "almost 100 GB", they run "on the order of 25 million code checkouts per day for CI", and at the peak they ran "several hundred internal git mirrors to deal with the load" (Anthropic).

Their answer was a new system called Scion and a review tool called Antique, both built by "a team of seven people" who "fully migrated to them in five months". Scion is internal to Anthropic, and the post says it "is by no means a suitable replacement for git for general use." (An unrelated open-source project by Carter Tran, mentioned below, uses the same name.)

Trellis is our attempt at a version anyone can run: source control and a code-hosting site built for agents, which we plan to release as open source. Before writing it, we wanted evidence for the decision everything else sits on: where it keeps its records.

Words used on this page
  • Branch. A named line of work, such as main. In trellis a branch is one row in a database that says which version of the code it points to.
  • Landing. Adding a finished change to a branch, so the branch's row now points to a newer version.
  • Transaction. A group of database writes that either all happen or none do.
  • Flush. Making sure a write has actually reached the disk, so a power cut cannot lose it. It is usually the slowest step of a single commit: on this laptop a full flush took 4.6 ms (median), and a lone Postgres landing took 5.2 ms (median).
  • Batching by one owner. One task takes every landing waiting for a branch and commits them together, paying for one flush instead of one each.
  • Slowest 1% (p99). 99 out of 100 landings finished at least this fast.
How Anthropic's system handles a branch

Anthropic's post says that moving a branch "is a compare-and-swap on a single Spanner row that happens separately from creating changesets." Compare-and-swap means: update the row only if it still holds the value you last read. Spanner is a database Google sells as a cloud service (Google Cloud). So, as we read it, even at Anthropic's scale each branch is one row that every move of that branch must go through; the post does not say how many changes each move carries. That row is what we measured here, with databases anyone can run themselves instead of Spanner.

The four databases, and why these
  • Postgres runs on one server and was already our plan for trellis. Open source under the PostgreSQL licence (postgresql.org).
  • YugabyteDB spreads data across many machines and accepts Postgres's SQL, because it reuses Postgres's query layer (its documentation). Our benchmark ran the same queries on both, with one table defined differently. The database itself is Apache-2.0; its separate management platform, YugabyteDB Anywhere, is not (its licence file).
  • FoundationDB is a key-value database from Apple that also spreads across machines and gives every transaction the strictest ordering guarantee there is, strict serializability (its documentation). Apache-2.0 (its licence).
  • SQLite is a database in a single file, which trellis's design uses in its development mode, on a single computer. Public domain (sqlite.org).
The question

In this benchmark, landing a change on a branch means four writes in one transaction: read the branch's row, raise its version by one, write a log entry, and write a record that this change landed. Only one landing on a branch can commit at a time. Postgres makes the others wait on a lock, YugabyteDB mostly makes them start again (797 retries at 256 agents), SQLite allows one writer at a time, and FoundationDB makes conflicting landings start again (39,315 retries at 1,000 agents). Trellis expects many agents landing on one branch, so we wanted to know how far that goes, and whether a different database moves the limit.

We also tested the alternative: one task owns the branch, takes every landing that is waiting (up to 1,024), and commits them as one transaction. We call it batching by one owner below.

What we measured

Landings on one branch, per second, with the slowest 1% of landings in brackets (the 99th percentile wait). Each cell is a 10-second run. Landings that started in the 10 seconds are counted even if they finished later, so at the busiest settings with one transaction per landing the rates are upper bounds.

DatabaseHow1 agent16 agents64 agents256 agents1,000 agents
Postgresone transaction per landing178 (10 ms)183 (671 ms)182 (1.6 s)199 (6.4 s)not run
Postgresbatched by one owner171 (12.6 ms)1,262 (26.9 ms)5,048 (25.8 ms)20,837 (24 ms)81,318 (41.8 ms)
YugabyteDBone transaction per landing438 (7.4 ms)68.1 (2.7 s)67.5 (9.7 s)37.8 (18.7 s)not run
YugabyteDBbatched by one owner448 (3.3 ms)3,013 (8.5 ms)10,347 (8.8 ms)22,270 (15 ms)29,784 (88.6 ms)
SQLiteone transaction per landing230 (8.1 ms)226 (1.7 s)222 (10.2 s)208 (12.4 s)214 (18.6 s)
SQLitebatched by one owner202 (10.8 ms)1,236 (42.9 ms)3,612 (87.9 ms)12,326 (55.3 ms)15,868 (144 ms)
FoundationDBone transaction per landing143 (22.6 ms)86.9 (4.5 s)68.5 (10.1 s)102 (13.1 s)186 (20.8 s)
FoundationDBbatched by one owner113 (19.6 ms)1,025 (44.3 ms)4,310 (33.8 ms)12,723 (54 ms)21,695 (184 ms)

"Not run": one transaction per landing needs one connection per agent. We expected 1,000 Postgres or YugabyteDB connections to use up this machine's memory, so we did not run them.

Writing and reading records. Writing: 8 writers send 5,000,000 object records in batches of 1,000, about 30% of them repeats that the database must skip. The rate counts every record sent, repeats included. Reading: 32 readers fetch one record at a time for 15 seconds.

DatabaseRecords sent a secondRecords read a secondTypical readSlowest 1% of reads
Postgres247,169157,5640.193 ms0.407 ms
YugabyteDB126,89724,4170.752 ms7.371 ms
SQLite26,19090,1060.173 ms2.719 ms
FoundationDB29,39929,9540.773 ms3.307 ms
What it shows
  1. With one transaction per landing, no database got far. Every result stayed between 38 and 438 landings a second on this machine, and adding agents only made them wait longer: in Postgres the slowest 1% went from 10 ms with one agent to 6.4 seconds with 256.
  2. Batching by one owner moved the limit far more than changing the database did. At 1,000 agents each database did 68 to 409 times its best one-transaction-per-landing result: Postgres 81,318 a second, YugabyteDB 29,784, FoundationDB 21,695, SQLite 15,868.
  3. Postgres was also fastest at writing and reading records on this machine: 247,169 records sent a second (about 70% of them new) and 157,564 read.
What we decided

We had planned to use Postgres, with SQLite for local development. These results support that plan, and we have made batching by one owner a requirement in trellis's design rather than an option: the way landings are committed mattered more than the database. We did not test CockroachDB, which an open-source implementation of the same design, Scion by Carter Tran, uses: its free Core edition was retired in November 2024, and self-hosted CockroachDB now comes only as its Enterprise edition, free for companies under $10M in revenue, under a source-available licence (SD Times, August 2024). Trellis will be open source, so it cannot depend on that. Before production we will repeat these runs on several machines in separate zones, which a laptop cannot show.

What happens next
  1. Repeat this on real servers: several machines in separate zones, with each write copied to a second machine before it is confirmed, as a production setup would.
  2. Build trellis's landing path around one owner per protected branch (such as main), and measure it with the full work of a landing, including rebasing the change and checking policy.
  3. Publish trellis's code once it runs. Until then, this project's benchmark code and results are public; trellis's are not yet.
What we did, in order
  1. We ran the databases directly on the laptop. Docker would not start on this machine, so Postgres, YugabyteDB and FoundationDB run as ordinary programs on their own ports, and SQLite runs inside the benchmark program, as it always does.
  2. Our first numbers were not comparable. On macOS, a plain fsync can leave data in the drive's own cache; a call named F_FULLFSYNC asks the drive to flush it (Apple's fsync page). In our recorded run the first took 0.051 ms and the second 4.624 ms (medians). FoundationDB uses F_FULLFSYNC on Apple machines (its source); Postgres and SQLite do not by default, so we switched them to it (Postgres, SQLite). YugabyteDB is set to sync on every write, but its median single-agent landing took 1.9 ms, less than one full flush, which suggests its sync is the plain kind. Read its results with that in mind.
  3. We threw away two runs. The first counted the time spent opening connections as part of the run. In the second, an earlier run we thought we had stopped was still going, so two runs shared the machine. Both are kept in the results folder, marked as discarded.
  4. Our own code understated FoundationDB. When batching, it checked each change's landing record one after another inside the transaction. With that fixed, a rerun gave 21,695 landings a second at 1,000 agents instead of 4,882. The rerun also used a fresh FoundationDB with different memory settings (3 GiB plus a 1 GiB cache, instead of 6 GiB), with the other databases stopped, so we cannot say how much of the difference the fix alone made; its one-transaction-per-landing results, which the fix did not touch, were slower in the rerun. The table shows the rerun.
  5. The laptop ran short of memory and disk. Late in the session macOS reported about 17.5 GiB of swap in use and the disk had 4.4 GiB free. We stopped the other databases and deleted their data before rerunning FoundationDB. The readings are in our notes (NOTES.md in the project folder).
Limits
  • One laptop (Apple M4 Pro, 14 cores, 24 GB, macOS 27.0.1). The databases and the program driving them share it.
  • Every database runs as a single node. A production setup copies each write to another machine before confirming it (a Postgres standby, or YugabyteDB and FoundationDB replicas), which adds time to every commit; none of these numbers include that.
  • A landing here is only its four writes. In trellis a landing also rebases the change and checks policy, and the agents here are tasks inside the benchmark program, not separate machines.
  • 5,000,000 records fit in memory. How each database behaves with billions of records is not measured here.
  • FoundationDB's landing runs and its writing and reading runs were separate runs with different memory settings, both listed in the results folder.
Sources

The design trellis starts from. Anthropic, Redesigning source control at Anthropic. https://www.anthropic.com/engineering/redesigning-source-control

An open implementation of that design. Carter Tran, Scion. https://github.com/CarterT27/scion

CockroachDB's licence change. SD Times, August 2024. sdtimes.com

Flushing on macOS. Apple, fsync(2): developer.apple.com. Postgres wal_sync_method: postgresql.org. SQLite PRAGMA fullfsync: sqlite.org. FoundationDB's file layer: github.com/apple/foundationdb.

Corrections

None yet. Any correction will be listed here and stay here.

Our own measurements, not peer-reviewed.

Labs are built in Nucleus. Research is done with Terramind Science.