self-host →

EC2 storage: NVMe vs gp3 vs tmpfs.

RunsOn launches the instance type you ask for, so the workspace disk is yours to pick: EBS gp3 by default, local NVMe on i and d families, or RAM with tmpfs: the workspace lives in memory, so the trade-off is capacity shared with the build, not durability.

Provisioned gp3 2.5× 402 MiB/s → 1,002 MiB/s seq read, same m8a.2xlarge; latency flat
Local NVMe by size 8.1× 503 MiB/s on i7i.large → 4.0 GiB/s on i7i.4xlarge
tmpfs for databases 8.9× 29,390 vs 3,297 TPS, pgbench, same m8a.2xlarge
  • Provisioned gp3 lifted sequential reads 2.5× on the same m8a.2xlarge (402 MiB/s to 1,002 MiB/s), but single-queue reads (1,791 to 1,792 IOPS) and synced writes (538 to 539 IOPS) barely moved: it buys bandwidth, not latency.
  • Local NVMe bandwidth grows with the instance: i7i.large reads 503 MiB/s, i7i.4xlarge 4.0 GiB/s (8.1×).
  • On the same m8a.2xlarge, tmpfs ran pgbench's read/write mix at 29,390 TPS against 3,297 on default gp3: 8.9× faster.
  • r8a.xlarge with tmpfs ($0.0021/min at spot) answers 1,054,041 QD1 reads and 912,188 synced writes per second: 87× and 77× the best local NVMe at 4 vCPU (i7i.xlarge, $0.0019) and 577× and 1,692× default EBS gp3 (m8a.xlarge, $0.0015); its workspace is 31 GiB, from RAM.

Sequential read by instance size

Local NVMe grows with the instance; EBS gp3 grows with what you provision. Right: random-read IOPS.

Sequential read1M blocks · MiB/s, higher is better

i7i · local NVMe · Xeon 8559C

  1. i7i.large 2 vCPU 503 MiB/s , random read 75k IOPS
  2. i7i.xlarge 4 vCPU 1,010 MiB/s , random read 150k IOPS
  3. i7i.2xlarge 8 vCPU 2.0 GiB/s , random read 300k IOPS
  4. i7i.4xlarge 16 vCPU 4.0 GiB/s , random read 589k IOPS

m8id · local NVMe · Xeon 6975P-C

  1. m8id.large 2 vCPU 226 MiB/s , random read 34k IOPS
  2. m8id.xlarge 4 vCPU 451 MiB/s , random read 67k IOPS
  3. m8id.2xlarge 8 vCPU 905 MiB/s , random read 134k IOPS
  4. m8id.4xlarge 16 vCPU 1.8 GiB/s , random read 269k IOPS

m9gd · local NVMe · Neoverse-V3

  1. m9gd.large 2 vCPU 293 MiB/s , random read 44k IOPS
  2. m9gd.xlarge 4 vCPU 585 MiB/s , random read 87k IOPS
  3. m9gd.2xlarge 8 vCPU 1.1 GiB/s , random read 175k IOPS

EBS gp3 · default and provisioned

  1. m8a.2xlarge default gp3 402 MiB/s , random read 3.0k IOPS
  2. m8a.2xlarge gp3 1000 MiB/s 1,002 MiB/s , random read 16k IOPS
  3. m8azn.xlarge default gp3 401 MiB/s , random read 3.0k IOPS
  4. m8azn.xlarge gp3 1000 MiB/s 1,002 MiB/s , random read 16k IOPS

tmpfs is off this scale: 18.5 GiB/s on r8a.2xlarge, from RAM.

Every storage option measured

fio inside the job workspace; random reads span three orders of magnitude (log bars). Other providers for context.

Instance Rand read Rand write QD1 read p99 Sync write Seq read Seq write $/min
i7i · local NVMe instance storeXeon 8559C
i7i.4xlarge 16 vCPU 128 GB local NVMe 589,309 339,203 12,258 200 µs 12,081 4.0 GiB/s 3.1 GiB/s $0.0101 $0.0255 OD
i7i.2xlarge 8 vCPU 64 GB local NVMe 300,465 165,109 12,324 251 µs 9,607 2.0 GiB/s 1.5 GiB/s $0.0055 $0.0129 OD
i7i.xlarge 4 vCPU 32 GB local NVMe 150,053 82,487 12,185 301 µs 11,883 1,010 MiB/s 788 MiB/s $0.0019 $0.0066 OD
i7i.large 2 vCPU 16 GB local NVMe 75,023 41,227 12,120 313 µs 13,180 503 MiB/s 395 MiB/s $0.0011 $0.0035 OD
m8id · local NVMe instance storeXeon 6975P-C
m8id.4xlarge 16 vCPU 64 GB local NVMe 268,804 134,243 11,343 100 µs 6,942 1.8 GiB/s 866 MiB/s $0.0057 $0.0177 OD
m8id.2xlarge 8 vCPU 32 GB local NVMe 134,258 67,075 10,342 313 µs 7,025 905 MiB/s 432 MiB/s $0.0028 $0.0090 OD
m8id.xlarge 4 vCPU 16 GB local NVMe 67,089 33,526 11,056 210 µs 7,841 451 MiB/s 216 MiB/s $0.0017 $0.0047 OD
m8id.large 2 vCPU 8 GB local NVMe 33,541 16,753 11,154 108 µs 5,555 226 MiB/s 108 MiB/s $0.0009 $0.0025 OD
m9gd · local NVMe instance storeNeoverse-V3
m9gd.2xlarge 8 vCPU 32 GB local NVMe 174,573 87,210 13,398 88 µs 17,495 1.1 GiB/s 560 MiB/s $0.0028 $0.0087 OD
m9gd.xlarge 4 vCPU 16 GB local NVMe 87,221 43,583 12,610 138 µs 11,264 585 MiB/s 280 MiB/s $0.0014 $0.0045 OD
m9gd.large 2 vCPU 8 GB local NVMe 43,608 21,784 13,126 104 µs 7,159 293 MiB/s 141 MiB/s $0.0008 $0.0024 OD
EBS gp3 · RunsOn default volume, and provisioned
m8a.2xlarge 8 vCPU 32 GB EBS gp3 2,995 2,995 1,791 856 µs 538 402 MiB/s 401 MiB/s $0.0029 $0.0084 OD
m8a.2xlarge 8 vCPU 32 GB gp3 1000 MiB/s 15,996 15,993 1,792 852 µs 539 1,002 MiB/s 1,001 MiB/s $0.0051 $0.0105 OD
c8a.large 2 vCPU 4 GB EBS gp3 2,991 2,993 1,809 807 µs 541 401 MiB/s 401 MiB/s $0.0009 $0.0021 OD
c8a.xlarge 4 vCPU 8 GB EBS gp3 2,994 2,993 1,745 930 µs 540 401 MiB/s 401 MiB/s $0.0016 $0.0039 OD
c8a.2xlarge 8 vCPU 16 GB EBS gp3 2,995 2,992 1,796 832 µs 539 401 MiB/s 401 MiB/s $0.0030 $0.0075 OD
c8g.large 2 vCPU 4 GB EBS gp3 2,993 2,994 1,779 815 µs 539 401 MiB/s 401 MiB/s $0.0008 $0.0016 OD
c8g.xlarge 4 vCPU 8 GB EBS gp3 2,992 2,994 1,703 889 µs 539 401 MiB/s 401 MiB/s $0.0013 $0.0030 OD
c8g.2xlarge 8 vCPU 16 GB EBS gp3 2,994 2,994 1,817 815 µs 540 401 MiB/s 401 MiB/s $0.0027 $0.0056 OD
m8a.large 2 vCPU 8 GB EBS gp3 2,994 2,993 1,749 770 µs 541 401 MiB/s 401 MiB/s $0.0009 $0.0023 OD
m8a.xlarge 4 vCPU 16 GB EBS gp3 2,993 2,993 1,828 840 µs 539 401 MiB/s 401 MiB/s $0.0015 $0.0044 OD
m8azn.large 2 vCPU 8 GB EBS gp3 2,994 2,994 1,827 815 µs 542 401 MiB/s 401 MiB/s $0.0011 $0.0037 OD
m8azn.xlarge 4 vCPU 16 GB EBS gp3 2,994 2,992 1,775 963 µs 541 401 MiB/s 401 MiB/s $0.0026 $0.0072 OD
m8azn.xlarge 4 vCPU 16 GB gp3 1000 MiB/s 15,994 15,991 1,775 856 µs 540 1,002 MiB/s 1,001 MiB/s $0.0047 $0.0093 OD
m8azn.3xlarge 12 vCPU 48 GB EBS gp3 2,997 2,996 1,827 766 µs 539 401 MiB/s 401 MiB/s $0.0078 $0.0210 OD
m8i.large 2 vCPU 8 GB EBS gp3 2,993 2,994 1,736 872 µs 534 401 MiB/s 401 MiB/s $0.0009 $0.0021 OD
m8i.xlarge 4 vCPU 16 GB EBS gp3 2,992 2,994 1,634 930 µs 508 401 MiB/s 401 MiB/s $0.0017 $0.0038 OD
m8i.2xlarge 8 vCPU 32 GB EBS gp3 2,992 2,994 1,559 1,036 µs 470 401 MiB/s 401 MiB/s $0.0033 $0.0074 OD
m8i-flex.large 2 vCPU 8 GB EBS gp3 2,994 2,994 1,745 881 µs 527 401 MiB/s 401 MiB/s $0.0010 $0.0020 OD
m8i-flex.xlarge 4 vCPU 16 GB EBS gp3 2,994 2,993 1,576 963 µs 527 401 MiB/s 401 MiB/s $0.0017 $0.0037 OD
m8i-flex.2xlarge 8 vCPU 32 GB EBS gp3 2,992 2,995 1,746 848 µs 516 401 MiB/s 401 MiB/s $0.0027 $0.0070 OD
m9g.large 2 vCPU 8 GB EBS gp3 2,992 2,994 1,660 963 µs 543 401 MiB/s 401 MiB/s $0.0010 $0.0019 OD
m9g.xlarge 4 vCPU 16 GB EBS gp3 2,994 2,993 1,818 938 µs 543 401 MiB/s 401 MiB/s $0.0018 $0.0036 OD
m9g.2xlarge 8 vCPU 32 GB EBS gp3 2,995 2,993 1,720 823 µs 543 401 MiB/s 401 MiB/s $0.0036 $0.0068 OD
r8a.large 2 vCPU 16 GB EBS gp3 2,991 2,994 1,842 881 µs 541 401 MiB/s 401 MiB/s $0.0010 $0.0030 OD
t8i.medium 2 vCPU 4 GB EBS gp3 3,000 2,998 1,750 799 µs 524 401 MiB/s 401 MiB/s $0.0007 $0.0011 OD
tmpfs · workspace in RAM
m8a.2xlarge 8 vCPU 32 GB tmpfs 4,111,775 3,663,155 1,108,954 <1 µs 931,027 18.1 GiB/s 10.1 GiB/s $0.0029 $0.0084 OD
m9g.2xlarge 8 vCPU 32 GB tmpfs 2,689,280 2,433,754 657,000 <1 µs 647,961 15.7 GiB/s 6.7 GiB/s $0.0036 $0.0068 OD
r8a.2xlarge 8 vCPU 64 GB tmpfs 4,207,889 3,669,702 1,098,003 <1 µs 877,674 18.5 GiB/s 10.1 GiB/s $0.0043 $0.0110 OD
m9g.xlarge 4 vCPU 16 GB tmpfs 2,634,992 2,450,656 655,954 <1 µs 647,658 15.2 GiB/s 4.5 GiB/s $0.0018 $0.0036 OD
r8a.xlarge 4 vCPU 32 GB tmpfs 4,014,510 3,665,859 1,054,041 <1 µs 912,188 18.2 GiB/s 9.9 GiB/s $0.0021 $0.0056 OD
Other providers, 8/4/2 vCPU x64 (hardware suite)
Namespace 8x16 8 vCPU 16 GB VM disk EPYC 1,137,038 423,854 78,141 12 µs 17,901 4.1 GiB/s 2.9 GiB/s $0.0120
Namespace 8x32 8 vCPU 32 GB VM disk EPYC 1,126,282 417,764 78,586 13 µs 18,160 4.2 GiB/s 2.9 GiB/s $0.0240
Namespace 4x16 4 vCPU 16 GB VM disk EPYC 1,011,926 436,056 78,615 12 µs 17,844 4.1 GiB/s 2.9 GiB/s $0.0120
Namespace 4x8 4 vCPU 8 GB VM disk EPYC 1,009,155 403,484 78,033 12 µs 17,941 4.1 GiB/s 3.0 GiB/s $0.0060
Blacksmith 4 vCPU 4 vCPU 16 GB VM disk EPYC 873,112 251,762 84,854 14 µs 18,024 6.9 GiB/s 1.6 GiB/s $0.0080
Blacksmith 8 vCPU 8 vCPU 32 GB VM disk EPYC 567,996 199,982 68,500 19 µs 15,392 4.0 GiB/s 1.7 GiB/s $0.0160
Blacksmith 2 vCPU 2 vCPU 8 GB VM disk EPYC 515,353 136,106 61,629 19 µs 15,532 4.7 GiB/s 1.9 GiB/s $0.0040
Avrea 2 vCPU 2 vCPU 8 GB VM disk EPYC 4585PX 454,066 132,755 45,672 20 µs 8,163 5.3 GiB/s 3.4 GiB/s $0.0040
Avrea 4 vCPU 4 vCPU 16 GB VM disk EPYC 4585PX 402,481 172,765 47,519 18 µs 8,386 4.6 GiB/s 3.1 GiB/s $0.0080
Ubicloud premium 8 vCPU 8 vCPU 32 GB VM disk Ryzen 9 7950X3D 362,984 19,859 9,657 408 µs 3,195 3.1 GiB/s 1.2 GiB/s $0.0080
Namespace 2x8 2 vCPU 8 GB VM disk EPYC 350,533 222,621 77,512 13 µs 18,068 4.1 GiB/s 2.9 GiB/s $0.0060
StarSling 8 vCPU 8 vCPU 32 GB VM disk EPYC 318,790 10,959 52,315 18 µs 2,812 2.5 GiB/s 2.0 GiB/s $0.0160
Ubicloud standard 8 vCPU 8 vCPU 32 GB VM disk EPYC 9454P 264,258 11,860 8,407 569 µs 1,670 2.6 GiB/s 689 MiB/s $0.0050
StarSling 4 vCPU 4 vCPU 16 GB VM disk EPYC 262,205 11,527 53,300 17 µs 3,023 2.5 GiB/s 3.4 GiB/s $0.0080
Avrea 8 vCPU 8 vCPU 32 GB VM disk EPYC 4585PX 245,805 139,439 43,414 23 µs 7,763 7.4 GiB/s 5.4 GiB/s $0.0160
Ubicloud premium 4 vCPU 4 vCPU 16 GB VM disk Ryzen 9 7950X3D 210,832 16,062 8,328 1,679 µs 1,343 2.7 GiB/s 807 MiB/s $0.0040
Ubicloud standard 4 vCPU 4 vCPU 16 GB VM disk EPYC 9454P 157,238 8,344 3,805 2,073 µs 578 2.2 GiB/s 250 MiB/s $0.0025
Warpbuild 2 vCPU 2 vCPU 8 GB VM disk Ryzen 9 9950X 151,759 72,474 26,143 56 µs 2,056 7.6 GiB/s 4.6 GiB/s $0.0040
Warpbuild 4 vCPU 4 vCPU 16 GB VM disk Ryzen 9 9950X 143,694 40,569 22,245 58 µs 1,980 7.8 GiB/s 5.1 GiB/s $0.0080
Ubicloud premium 2 vCPU 2 vCPU 8 GB VM disk Ryzen 9 7950X3D 138,040 64,617 5,988 1,106 µs 2,391 2.8 GiB/s 833 MiB/s $0.0020
Ubicloud standard 2 vCPU 2 vCPU 8 GB VM disk EPYC 9454P 106,887 46,311 6,847 864 µs 1,549 2.3 GiB/s 398 MiB/s $0.0013
Warpbuild 8 vCPU 8 vCPU 32 GB VM disk Ryzen 9 9950X 98,888 44,952 19,636 60 µs 1,813 7.9 GiB/s 4.5 GiB/s $0.0160
GitHub 8-core 8 vCPU 32 GB VM disk Xeon 8573C 38,954 18,761 8,049 192 µs 3,968 784 MiB/s 532 MiB/s $0.0220
GitHub 4-core 4 vCPU 16 GB network disk EPYC 7763 19,587 11,712 6,843 251 µs 3,262 394 MiB/s 394 MiB/s $0.0120
GitHub 2-core 2 vCPU 8 GB VM disk EPYC 7763 9,378 8,712 6,531 289 µs 3,904 199 MiB/s 199 MiB/s $0.0060
AWS CodeBuild medium 4 vCPU 8 GB EBS Xeon 8275CL 2,990 2,967 1,748 778 µs 559 252 MiB/s 252 MiB/s $0.0100
AWS CodeBuild small 2 vCPU 3 GB EBS Xeon 8124M 2,988 2,969 1,755 791 µs 562 252 MiB/s 252 MiB/s $0.0050
AWS CodeBuild large 8 vCPU 16 GB EBS Xeon 8124M 2,988 2,970 1,763 799 µs 559 252 MiB/s 252 MiB/s $0.0200
  • IOPS are 4k blocks · QD32 keeps 32 requests in flight, QD1 one
  • $/min: EC2 spot + EBS, on-demand (OD) under it; a dash means no price yet. The RunsOn license is a fixed cost, not included
More findings8: every NVMe family, provisioned gp3, tmpfs
  • i7i: random read climbs from 75,023 IOPS on i7i.large to 589,309 on i7i.4xlarge (7.9×), while single-request (QD1) reads stay between 12,120 and 12,324 IOPS.
  • m8id: random read climbs from 33,541 IOPS on m8id.large to 268,804 on m8id.4xlarge (8.0×), while single-request (QD1) reads stay between 10,342 and 11,343 IOPS.
  • m9gd: random read climbs from 43,608 IOPS on m9gd.large to 174,573 on m9gd.2xlarge (4.0×), while single-request (QD1) reads stay between 12,610 and 13,398 IOPS.
  • On m8azn.xlarge, gp3 provisioned at 1,000 MiB/s and 16,000 IOPS delivers it: 1,002 MiB/s and 15,994 random-read IOPS, against 401 MiB/s and 2,994 on the default volume. QD1 reads barely move (1,775 → 1,775 IOPS): provisioning buys throughput, not latency.
  • tmpfs on m9g.xlarge answers 2,634,992 random-read IOPS and 647,658 synced writes per second; the same m9g.xlarge on default gp3 manages 2,994 and 543. The price is capacity: the workspace is 15 GiB of RAM.
  • tmpfs on m8a.2xlarge answers 4,111,775 random-read IOPS and 931,027 synced writes per second; the same m8a.2xlarge on default gp3 manages 2,995 and 538. The price is capacity: the workspace is 31 GiB of RAM.
  • tmpfs on m9g.2xlarge answers 2,689,280 random-read IOPS and 647,961 synced writes per second; the same m9g.2xlarge on default gp3 manages 2,995 and 543. The price is capacity: the workspace is 31 GiB of RAM.
  • tmpfs on r8a.2xlarge answers 4,207,889 random-read IOPS and 877,674 synced writes per second; c8a.2xlarge (same CPU, 16 vs 64 GiB RAM) on default gp3 manages 2,995 and 539. The price is capacity: the workspace is 62 GiB of RAM.

What storage does to real builds

The same three builds on RunsOn runners that differ by storage, one 4 vCPU runner per kind first.

Runner Rust TypeScript bun install Docker $/Rust build
RunsOn x6428 runners
m8azn.xlarge 4 vCPU 16 GB EBS gp3 EPYC 9R05 1m 53s56s 21s 8m 13s $0.0079
m8a.xlarge 4 vCPU 16 GB EBS gp3 EPYC 9R45 1m 59s1m 01s 21s 9m 05s $0.0050
c8a.xlarge 4 vCPU 8 GB EBS gp3 EPYC 9R45 2m 05s1m 03s 21s n/a: Not run: the PostHog Docker build needs more than 8 GB of memory; it ran out of memory on 8 GB runners. $0.0044
m8i-flex.xlarge 4 vCPU 16 GB EBS gp3 Xeon 6975P-C 2m 56s1m 28s 22s 12m 15s $0.0065
m8i.xlarge 4 vCPU 16 GB EBS gp3 Xeon 6975P-C 2m 59s1m 29s 23s 12m 10s $0.0068
m8azn.3xlarge 12 vCPU 48 GB EBS gp3 EPYC 9R05 1m 10s37s 21s 4m 52s $0.0178
c8a.2xlarge 8 vCPU 16 GB EBS gp3 EPYC 9R45 1m 26s47s 25s 7m 19s $0.0072
m8a.2xlarge 8 vCPU 32 GB EBS gp3 EPYC 9R45 1m 27s42s 22s 5m 39s $0.0069
m8i.2xlarge 8 vCPU 32 GB EBS gp3 Xeon 6975P-C 1m 57s55s 20s 7m 18s $0.0092
m8i-flex.2xlarge 8 vCPU 32 GB EBS gp3 Xeon 6975P-C 1m 59s58s 22s 7m 29s $0.0101
m8azn.large 2 vCPU 8 GB EBS gp3 EPYC 9R05 2m 51s1m 45s 20s n/a: Not run: the PostHog Docker build needs more than 8 GB of memory; it ran out of memory on 8 GB runners. $0.0047
r8a.large 2 vCPU 16 GB EBS gp3 EPYC 9R45 3m 06s1m 41s 22s 11m 18s $0.0040
m8a.large 2 vCPU 8 GB EBS gp3 EPYC 9R45 3m 12s1m 37s 20s n/a: Not run: the PostHog Docker build needs more than 8 GB of memory; it ran out of memory on 8 GB runners. $0.0088
c8a.large 2 vCPU 4 GB EBS gp3 EPYC 9R45 3m 39sfailed: out of memory: 4 GB was not enough on this runner for the opencode typecheck, even with turbo limited to 4 tasks: TypeScript processes are killed out of memory (exit 137). 16 GB passes. It has 3.7 GiB of swap (zram). — n/a: Not run: the PostHog Docker build needs more than 8 GB of memory; it ran out of memory on 8 GB runners. $0.0039
m8i.large 2 vCPU 8 GB EBS gp3 Xeon 6975P-C 5m 12s2m 43s 21s n/a: Not run: the PostHog Docker build needs more than 8 GB of memory; it ran out of memory on 8 GB runners. $0.0066
m8i-flex.large 2 vCPU 8 GB EBS gp3 Xeon 6975P-C 5m 18s2m 36s 20s n/a: Not run: the PostHog Docker build needs more than 8 GB of memory; it ran out of memory on 8 GB runners. $0.0060
t8i.medium 2 vCPU 4 GB EBS gp3 Xeon 6975P-C 5m 34sfailed: out of memory: 4 GB was not enough on this runner for the opencode typecheck, even with turbo limited to 4 tasks: TypeScript processes are killed out of memory (exit 137). 16 GB passes. It has 3.7 GiB of swap (zram). — n/a: Not run: the PostHog Docker build needs more than 8 GB of memory; it ran out of memory on 8 GB runners. $0.0046
m8azn.xlarge 4 vCPU 16 GB gp3 1000 MiB/s EPYC 9R05 1m 54s45s 10s 6m 42s $0.0136
m8a.2xlarge 8 vCPU 32 GB gp3 1000 MiB/s EPYC 9R45 1m 26s33s 11s 4m 26s $0.0122
m8id.xlarge 4 vCPU 16 GB local NVMe Xeon 6975P-C 2m 57s1m 20s 16s 9m 18s $0.0071
i7i.xlarge 4 vCPU 32 GB local NVMe Xeon 8559C 3m 06s1m 17s 11s 8m 34s $0.0077
m8id.2xlarge 8 vCPU 32 GB local NVMe Xeon 6975P-C 1m 56s44s 10s 5m 49s $0.0116
i7i.2xlarge 8 vCPU 64 GB local NVMe Xeon 8559C 1m 57s47s 10s 5m 47s $0.0142
m8id.large 2 vCPU 8 GB local NVMe Xeon 6975P-C 5m 02s3m 07s 36s n/a: Not run: the PostHog Docker build needs more than 8 GB of memory; it ran out of memory on 8 GB runners. $0.0139
i7i.large 2 vCPU 16 GB local NVMe Xeon 8559C 5m 18s2m 23s 16s 14m 51s $0.0065
r8a.xlarge 4 vCPU 32 GB tmpfs EPYC 9R45 2m 06s48s 8s n/a: Not run: needs more than 32 GB of RAM with tmpfs, where Docker's data root lives in RAM; PostHog's layers plus the build's own memory exceeded it and the runner was shut down mid-build. The 64 GB tmpfs runner builds it. $0.0065
r8a.2xlarge 8 vCPU 64 GB tmpfs EPYC 9R45 1m 28s31s 8s 3m 46s $0.0107
m8a.2xlarge 8 vCPU 32 GB tmpfs EPYC 9R45 1m 29s30s 8s n/a: Not run: needs more than 32 GB of RAM with tmpfs, where Docker's data root lives in RAM; PostHog's layers plus the build's own memory exceeded it and the runner was shut down mid-build. The 64 GB tmpfs runner builds it. $0.0075
RunsOn arm6411 runners
m9g.xlarge 4 vCPU 16 GB EBS gp3 Neoverse-V3 2m 02s1m 00s 22s 9m 10s $0.0091
c8g.xlarge 4 vCPU 8 GB EBS gp3 Neoverse-V2 2m 43s1m 20s 22s n/a: Not run: the PostHog Docker build needs more than 8 GB of memory; it ran out of memory on 8 GB runners. $0.0057
m9g.2xlarge 8 vCPU 32 GB EBS gp3 Neoverse-V3 1m 28s42s 20s 5m 54s $0.0079
c8g.2xlarge 8 vCPU 16 GB EBS gp3 Neoverse-V2 1m 54s53s 26s 8m 20s $0.0083
m9g.large 2 vCPU 8 GB EBS gp3 Neoverse-V3 3m 13s1m 40s 19s n/a: Not run: the PostHog Docker build needs more than 8 GB of memory; it ran out of memory on 8 GB runners. $0.0075
c8g.large 2 vCPU 4 GB EBS gp3 Neoverse-V2 5m 17sfailed: out of memory: 4 GB was not enough on this runner for the opencode typecheck, even with turbo limited to 4 tasks: TypeScript processes are killed out of memory (exit 137). 16 GB passes. It has 3.7 GiB of swap (zram). — n/a: Not run: the PostHog Docker build needs more than 8 GB of memory; it ran out of memory on 8 GB runners. $0.0048
m9gd.xlarge 4 vCPU 16 GB local NVMe Neoverse-V3 2m 04s50s 13s 6m 23s $0.0118
m9gd.2xlarge 8 vCPU 32 GB local NVMe Neoverse-V3 1m 30s30s 8s 4m 33s $0.0188
m9gd.large 2 vCPU 8 GB local NVMe Neoverse-V3 3m 09s1m 40s 29s n/a: Not run: the PostHog Docker build needs more than 8 GB of memory; it ran out of memory on 8 GB runners. $0.0092
m9g.xlarge 4 vCPU 16 GB tmpfs Neoverse-V3 2m 04s46s 9s n/a: Not run: needs more than 32 GB of RAM with tmpfs, where Docker's data root lives in RAM; PostHog's layers plus the build's own memory exceeded it and the runner was shut down mid-build. The 64 GB tmpfs runner builds it. $0.0091
m9g.2xlarge 8 vCPU 32 GB tmpfs Neoverse-V3 1m 31s29s 8s n/a: Not run: needs more than 32 GB of RAM with tmpfs, where Docker's data root lives in RAM; PostHog's layers plus the build's own memory exceeded it and the runner was shut down mid-build. The 64 GB tmpfs runner builds it. $0.0084
  • Groups: EBS gp3, default · EBS gp3, provisioned · local NVMe · tmpfs
  • Cost at EC2 spot, RunsOn's default
  • Every machine next to the other providers: RunsOn profile
Same CPU, different disk24 comparisons
  • m8a.2xlarge on EBS gp3 and on gp3 1000 MiB/s: Rust even within run-to-run spread (1m 25s–1m 29s on EBS gp3, 1m 23s–1m 31s on gp3 1000 MiB/s); TypeScript even within run-to-run spread (39s–48s on EBS gp3, 32s–39s on gp3 1000 MiB/s); Docker 4m 26s on gp3 1000 MiB/s vs 5m 39s.
  • m8a.2xlarge on EBS gp3 and on tmpfs: Rust even within run-to-run spread (1m 25s–1m 29s on EBS gp3, 1m 26s–1m 33s on tmpfs); TypeScript 30s on tmpfs vs 42s.
  • m8azn.xlarge on EBS gp3 and on gp3 1000 MiB/s: Rust even within run-to-run spread (1m 50s–1m 57s on EBS gp3, 1m 51s–1m 55s on gp3 1000 MiB/s); TypeScript 45s on gp3 1000 MiB/s vs 56s; Docker 6m 42s on gp3 1000 MiB/s vs 8m 13s.
  • m9g.xlarge on EBS gp3 and on tmpfs: Rust even within run-to-run spread (1m 59s–2m 05s on EBS gp3, 1m 58s–2m 06s on tmpfs); TypeScript 46s on tmpfs vs 1m 00s.
  • m9g.2xlarge on EBS gp3 and on tmpfs: Rust even within run-to-run spread (1m 25s–1m 31s on EBS gp3, 1m 24s–1m 42s on tmpfs); TypeScript 29s on tmpfs vs 42s.
  • m8a.2xlarge on gp3 1000 MiB/s and on tmpfs: Rust even within run-to-run spread (1m 23s–1m 31s on gp3 1000 MiB/s, 1m 26s–1m 33s on tmpfs); TypeScript even within run-to-run spread (32s–39s on gp3 1000 MiB/s, 29s–33s on tmpfs).
  • m8i.2xlarge (EBS gp3) and m8id.2xlarge (local NVMe) share the Xeon 6975P-C: Rust even within run-to-run spread (1m 51s–2m 00s on EBS gp3, 1m 51s–2m 02s on local NVMe); TypeScript 44s on local NVMe vs 55s; Docker 5m 49s on local NVMe vs 7m 18s.
  • m8i-flex.2xlarge (EBS gp3) and m8id.2xlarge (local NVMe) share the Xeon 6975P-C: Rust even within run-to-run spread (1m 54s–2m 06s on EBS gp3, 1m 51s–2m 02s on local NVMe); TypeScript 44s on local NVMe vs 58s; Docker 5m 49s on local NVMe vs 7m 29s.
  • m8i-flex.large (EBS gp3) and m8id.large (local NVMe) share the Xeon 6975P-C: Rust even within run-to-run spread (4m 57s–5m 27s on EBS gp3, 4m 50s–5m 07s on local NVMe); TypeScript 2m 36s on EBS gp3 vs 3m 07s.
  • m8i-flex.xlarge (EBS gp3) and m8id.xlarge (local NVMe) share the Xeon 6975P-C: Rust even within run-to-run spread (2m 53s–3m 02s on EBS gp3, 2m 50s–3m 00s on local NVMe); TypeScript 1m 20s on local NVMe vs 1m 28s; Docker 9m 18s on local NVMe vs 12m 15s.
  • m8i.large (EBS gp3) and m8id.large (local NVMe) share the Xeon 6975P-C: Rust even within run-to-run spread (4m 58s–5m 35s on EBS gp3, 4m 50s–5m 07s on local NVMe); TypeScript 2m 43s on EBS gp3 vs 3m 07s.
  • m8i.xlarge (EBS gp3) and m8id.xlarge (local NVMe) share the Xeon 6975P-C: Rust even within run-to-run spread (2m 56s–3m 00s on EBS gp3, 2m 50s–3m 00s on local NVMe); TypeScript 1m 20s on local NVMe vs 1m 29s; Docker 9m 18s on local NVMe vs 12m 10s.
  • m9g.xlarge (EBS gp3) and m9gd.xlarge (local NVMe) share the Neoverse-V3: Rust even within run-to-run spread (1m 59s–2m 05s on EBS gp3, 1m 56s–2m 07s on local NVMe); TypeScript 50s on local NVMe vs 1m 00s; Docker 6m 23s on local NVMe vs 9m 10s.
  • m9g.2xlarge (EBS gp3) and m9gd.2xlarge (local NVMe) share the Neoverse-V3: Rust even within run-to-run spread (1m 25s–1m 31s on EBS gp3, 1m 20s–1m 36s on local NVMe); TypeScript 30s on local NVMe vs 42s; Docker 4m 33s on local NVMe vs 5m 54s.
  • m9g.large (EBS gp3) and m9gd.large (local NVMe) share the Neoverse-V3: Rust even within run-to-run spread (3m 01s–3m 25s on EBS gp3, 3m 01s–3m 10s on local NVMe); TypeScript within 1s of each other.
  • m9gd.2xlarge (local NVMe) and m9g.2xlarge (tmpfs) share the Neoverse-V3: Rust even within run-to-run spread (1m 20s–1m 36s on local NVMe, 1m 24s–1m 42s on tmpfs); TypeScript even within run-to-run spread (28s–31s on local NVMe, 29s–32s on tmpfs).
  • m9gd.xlarge (local NVMe) and m9g.xlarge (tmpfs) share the Neoverse-V3: Rust even within run-to-run spread (1m 56s–2m 07s on local NVMe, 1m 58s–2m 06s on tmpfs); TypeScript 46s on tmpfs vs 50s.
  • c8a.xlarge (EBS gp3) and r8a.xlarge (tmpfs) share the EPYC 9R45 (RAM differs: 8 vs 32 GiB): Rust even within run-to-run spread (1m 57s–2m 09s on EBS gp3, 1m 59s–2m 14s on tmpfs); TypeScript 48s on tmpfs vs 1m 03s.
  • c8a.2xlarge (EBS gp3) and m8a.2xlarge (gp3 1000 MiB/s) share the EPYC 9R45 (RAM differs: 16 vs 32 GiB): Rust even within run-to-run spread (1m 21s–1m 32s on EBS gp3, 1m 23s–1m 31s on gp3 1000 MiB/s); TypeScript 33s on gp3 1000 MiB/s vs 47s; Docker 4m 26s on gp3 1000 MiB/s vs 7m 19s.
  • c8a.2xlarge (EBS gp3) and m8a.2xlarge (tmpfs) share the EPYC 9R45 (RAM differs: 16 vs 32 GiB): Rust even within run-to-run spread (1m 21s–1m 32s on EBS gp3, 1m 26s–1m 33s on tmpfs); TypeScript 30s on tmpfs vs 47s.
  • c8a.2xlarge (EBS gp3) and r8a.2xlarge (tmpfs) share the EPYC 9R45 (RAM differs: 16 vs 64 GiB): Rust even within run-to-run spread (1m 21s–1m 32s on EBS gp3, 1m 24s–1m 30s on tmpfs); TypeScript 31s on tmpfs vs 47s; Docker 3m 46s on tmpfs vs 7m 19s.
  • m8a.2xlarge (EBS gp3) and r8a.2xlarge (tmpfs) share the EPYC 9R45 (RAM differs: 32 vs 64 GiB): Rust even within run-to-run spread (1m 25s–1m 29s on EBS gp3, 1m 24s–1m 30s on tmpfs); TypeScript 31s on tmpfs vs 42s; Docker 3m 46s on tmpfs vs 5m 39s.
  • m8a.xlarge (EBS gp3) and r8a.xlarge (tmpfs) share the EPYC 9R45 (RAM differs: 16 vs 32 GiB): Rust even within run-to-run spread (1m 55s–2m 11s on EBS gp3, 1m 59s–2m 14s on tmpfs); TypeScript 48s on tmpfs vs 1m 01s.
  • m8a.2xlarge (gp3 1000 MiB/s) and r8a.2xlarge (tmpfs) share the EPYC 9R45 (RAM differs: 32 vs 64 GiB): Rust even within run-to-run spread (1m 23s–1m 31s on gp3 1000 MiB/s, 1m 24s–1m 30s on tmpfs); TypeScript even within run-to-run spread (32s–39s on gp3 1000 MiB/s, 29s–33s on tmpfs); Docker 3m 46s on tmpfs vs 4m 26s.

How it's measured

Methodology

The same fio tests as the runner table, inside the job workspace, on every size of each family. The jobs ran on RunsOn's default capacity: 24 on spot and 21 on on-demand, its fallback. 6 were interrupted on spot: shown as failures and left out of the medians, so an interruption never touches a timing.