Public benchmark results
3 to 50x on damaged networks.
We benchmarked RIFT, our in-development transport, against plain HTTPS across 25 network conditions, 193 runs, every file SHA-256 verified on arrival. The ties and the losses are published with everything else.
What runs in your browser today
Right now, dragging a file into Forma uploads it in parallel chunks over ordinary HTTPS, straight from your browser to Google Cloud Storage, and that path already resumes on its own if the connection drops. RIFT, benchmarked below, is the QUIC and BBR transport we are building for an upcoming desktop and CLI uploader. What follows are lab measurements of that transport, published early because we build in the open.
What we measured
A. RIFT
Our in-development transport. Built on QUIC and BBR, with content addressed manifests and crash safe resume. Not yet in the browser app; benchmarked here ahead of its desktop and CLI release.
B. Plain HTTPS
curl over HTTP/2 to nginx, TLS 1.3, WebDAV PUT to disk. The same upload path nearly every product on the internet uses.
Both sides run the same AES-256 class crypto, so the comparison is transport, not cipher. One 2 GiB incompressible file, medians of 5 interleaved reps per cell, run on GCE with Linux netem.
Matrix completed 3 July 2026: 25 of 25 cells, 193 runs, on GCE (n2d-standard-8, Ubuntu 24.04, kernel 6.17), veth namespaces, tc netem on both egresses, HTB rate caps, iperf3 calibration per cell, A/B interleaved per rep.
TCP ran 2.6 hours per upload, verified 3 times.
14 publish as DNF (did not finish); in the 15th we let the uploads run to completion, 2.6 hours each. RIFT held 61 to 90 MB/s on every 1 Gbit cell and 11.2 to 11.7 MB/s on every 100 Mbit cell, across every condition tested.
A tie on clean networks, as physics demands.
RIFT's loss on clean gigabit. Userspace crypto pays a CPU cost that kernel TCP does not. We publish it anyway.
Every cell, plotted
The full matrix
All 25 conditions, medians of 5 interleaved reps per cell, goodput in MB/s.
| Loss | RTT | Link | Ours (MB/s) | HTTPS (MB/s) | Ratio | Note |
|---|---|---|---|---|---|---|
| 0% | 5 ms | 100 Mbit | 11.67 | 11.89 | 0.98x | Clean LAN: a tie, as physics demands. |
| 0% | 100 ms | 100 Mbit | 11.53 | 11.81 | 0.98x | Tie. |
| 0% | 200 ms | 100 Mbit | 11.35 | 11.71 | 0.97x | Tie. |
| 0% | 5 ms | 1 Gbit | 90.16 | 117.91 | 0.76x | We lose clean gigabit. Userspace crypto CPU cost without NIC UDP offload. Published anyway. |
| 0% | 100 ms | 1 Gbit | 86.61 | 25.72 | 3.37x | TCP window limited on the long fat pipe. |
| 0% | 200 ms | 1 Gbit | 78.99 | 12.86 | 6.14x | Intercontinental fiber profile. |
| 1% | 5 ms | 100 Mbit | 11.67 | 6.29 | 1.85x | TCP loses half its speed to 1% loss. |
| 1% | 5 ms | 1 Gbit | 88.00 | 7.47 | 11.78x | Our transport unaffected by loss, TCP collapses. |
| 1% | 100 ms | 100 Mbit | 11.36 | 0.23 | 50x | TCP ran 2.6 hours per upload, verified 3 times. |
| 1% | 100 ms | 1 Gbit | 81.57 | DNF | ≥68x | TCP did not finish 2 GiB inside 30 min. |
| 1% | 200 ms | 100 Mbit | 11.20 | DNF | ≥9.4x | DNF. |
| 1% | 200 ms | 1 Gbit | 71.57 | DNF | ≥60x | DNF. |
| 2% | 5 ms | 100 Mbit | 11.60 | 2.88 | 4.03x | |
| 2% | 5 ms | 1 Gbit | 85.77 | 3.14 | 27.28x | Both completed, no cap needed. |
| 2% | 100 ms | 100 Mbit | 11.28 | DNF | ≥9.5x | The kill criterion cell. Bar was 3x. |
| 2% | 100 ms | 1 Gbit | 79.18 | DNF | ≥66x | |
| 2% | 200 ms | 100 Mbit | 11.30 | DNF | ≥9.5x | |
| 2% | 200 ms | 1 Gbit | 68.57 | DNF | ≥57x | |
| 5% | 5 ms | 100 Mbit | 11.53 | DNF | ≥9.7x | TCP DNFs at 5% loss even on a 5 ms LAN. |
| 5% | 5 ms | 1 Gbit | 87.33 | DNF | ≥73x | |
| 5% | 100 ms | 100 Mbit | 11.34 | DNF | ≥9.5x | |
| 5% | 100 ms | 1 Gbit | 79.34 | DNF | ≥66x | |
| 5% | 200 ms | 100 Mbit | 11.30 | DNF | ≥9.5x | |
| 5% | 200 ms | 1 Gbit | 61.15 | DNF | ≥51x | Worst i.i.d. cell. Our transport still 61 MB/s. |
| 5% / 25% correlated | 200 ms | 1 Gbit | 75.95 | DNF | ≥64x | Kill criterion 2, bar was 2x. Bursty loss helped our transport. |
DNF means did not finish: the HTTPS upload was capped at 30 minutes and had not completed the 2 GiB file. The published ratio is a floor computed against that cap, so the true ratio is higher. 14 rows publish as DNF. A 15th condition, 1% loss at 100 ms on 100 Mbit, also could not finish inside 30 minutes; there we let three uploads run to completion, 2.6 hours each, which is where the measured 50x comes from. Its fourth rep hit the cap and is logged in the raw data.
Honest caveats
- These are netem lab numbers: synthetic, independent packet loss and fixed delay. Real networks have bursty, correlated loss, which narrows the advantage. The correlated loss row exists in the matrix for exactly that reason, and it is published with everything else.
- Clean gigabit is a real loss for us, 0.76x. Userspace QUIC pays a CPU tax that kernel TCP does not, and this test VM's NIC lacks UDP segmentation offload. Production ingest hardware, Hetzner bare metal, has it, and we will remeasure this number there.
- The corpus is one 2 GiB file, a cost control after discovering that TCP crawl cells run 2.6 hours per rep. A 10 GiB validation of the headline cells is queued behind the full matrix.
- Single flow, single machine, no competing traffic. Fairness under contention is a v1 measurement.
Reproduce it
The raw per-run data behind this table is downloadable now.
The harness that reruns the full matrix with one command is being packaged for public release.
Damaged networks are where RIFT will pay for itself.
Your upload today already resumes automatically if the connection drops. RIFT is what we're building to make the worst networks fast too.
Send files free