Benchmarks and methodology
Every performance number Adjoint publishes is either measured (and we say where and how) or illustrative (and we say so). This page is the source of truth behind the numbers on the product page.
Time to a ready clone (TTFC)
TTFC — time-to-first-clone — is measured from instance creation to the
instance reporting Ready, using control-plane object timestamps (1-second
granularity). Developer-perceived wall-clock around adj clone --wait tracks
it within about a second.
Measured results
Three independent benchmark runs (2026-07-03, 2026-07-16, 2026-07-17), each
claiming 9–10 clones sequentially from a warm pool (targetWarm=10), on a
SINGLE_AZ_1 FSx for OpenZFS filesystem (128 MB/s throughput, 1000 IOPS) in
us-east-2:
| Path | p50 | p95 | Notes |
|---|---|---|---|
| Warm pool claim | 15–16 s | 25–30 s | reproduced across all three runs |
| On demand (pool empty) | ~99 s | — | FSx volume creation dominates |
| On demand, under FSx load | up to ~10 min | — | worst observed case (see below) |
Details that matter:
- Warm-claim latency is size-independent. Between runs the golden grew ~8× (86 MB → 0.7 GiB) with no change in TTFC — a warm claim re-binds an already-cloned volume; no data is copied.
- The ~15 s floor is our own reconcile tick, not storage: the pool controller re-checks every 15 seconds, so p50 sits at one tick and p95 at two.
- On-demand cost is an AWS API floor. Creating an FSx OpenZFS volume from a snapshot takes about 2 minutes regardless of data size, and FSx serializes volume creation at roughly one per minute per filesystem. That serialization is why a burst of on-demand clones queues: our worst measured sample — 10 minutes — was a claim that raced an empty pool while FSx was already busy creating volumes. This is exactly what warm pools exist to hide; see Clone pools.
- These are burst benchmarks — ~10 sequential claims — not sustained many-developer concurrency. Sustained-concurrency behavior is on our bench list.
Storage efficiency
Clones are FSx for OpenZFS copy-on-write children of the golden snapshot: a clone stores only the blocks it changes. Total storage follows base + Σ(each clone's changed blocks) — it does not multiply by clone count.
Measured results
From our FSx CoW validation battery (10 GB golden, measured via FSx
UsedStorageCapacity):
| Scenario | Measured total vs. full copies |
|---|---|
| Golden + 10 clones, no changes yet | 1.115× the golden's size (~126 MB overhead per clone) — vs. 11× for full copies |
| Golden + 10 clones, after 120 s of heavy pgbench writes on each | 1.366× (~276 MB of changed blocks per clone) |
The 1.12× number on the product page
That figure is an illustrative model, not a measurement: a 500 GB golden
plus 10 developers each changing 6 GB is 560 GB ≈ 1.12× — assuming, pessimistically, that
every changed byte costs its full size. The measured numbers above are the
empirical anchors; your ratio depends entirely on how much your developers
change. Write-heavy work — table rewrites, index rebuilds, VACUUM FULL,
bulk updates — diverges clones faster and moves the ratio up. Storage is
cheap relative to full copies in every scenario we've measured, but
copy-on-write is not magic: you pay for what you change.
Query performance on a clone
A clone is fit for functional and integration work, not as a production
performance replica. Measured on a medium clone (0.5 vCPU / 512 Mi, the
default), pgbench with 4 clients:
- Read-only: ~12,000 TPS at sub-millisecond latency (cache/CPU-bound — insensitive to FSx sizing in our tests).
- TPC-B read/write: ~850 TPS at the 128 MB/s / 1000 IOPS baseline — roughly half of node-local disk, the cost of network-attached storage with synchronous WAL writes.
- IOPS is the knob for write-heavy work, throughput mostly isn't: raising provisioned IOPS 1000 → 3000 took TPC-B to ~1,900–2,100 TPS even at the cheapest throughput tier; raising throughput 8× at fixed IOPS gained ~29%.
- The filesystem is shared. All clones on a cluster share one FSx
filesystem's throughput and IOPS. Ten clones running heavy load
simultaneously will contend — size FSx for the sum of concurrent
activity, not per developer (
adj cluster provision --fsx-throughput/--fsx-storage-gib).
Reproducing these numbers
The TTFC harness ships with the provisioning bundle
(verify/ttfc.sh in the embedded module — export it with
adj cluster bundle export): it drains and claims against your own pool and
prints per-clone timings. Storage amplification is visible in the FSx console
as UsedStorageCapacity before and after cloning. If your measurements
disagree with this page, we want to know:
[email protected].