Benchmarks

One laptop, not a controlled run

A pet shop built eight ways from the same contract, then measured. The numbers are real and public, and they are from a single Mac. Read the shape, not the third digit.

Every app and PostgreSQL 17 ran on the same machine as the load generator, each held to 2 CPUs and 2 GiB, in the framework's documented production server. Each scenario was run five times; the tables show the median. The percentage beside a throughput figure is how far apart the slowest and fastest run were, as a share of the median, so a large one means the runs disagree.

The apps are ours, written from a shared contract, and the maintainers of the other projects have not reviewed them yet. If you maintain one and the app is not idiomatic or is badly configured, open an issue or a pull request and the runs are redone. This page ranks nothing: effort and capability are separate tracks, and a framework that is faster here may give you less to start with. A run on dedicated cloud machines has not been made yet.

Gin, FastAPI and Sinatra were added later and measured in a second session on the same laptop (2026-10-17 and 2026-10-18), so compare them to the other rows with the same caution as any two rows here.

Throughput

Requests per second, higher is better. n/a means the app has no admin to measure; none means the admin was measured and no request succeeded.

Applistpetorderadminmix
Go baseline (chi, pgx, sqlc)3,822 (40%)22,589 (5%)10,126 (4%)n/a6,936 (3%)
tanGO v0.5.03,138 (34%)20,707 (17%)9,746 (36%)1,418 (11%)6,427 (9%)
Fuego v0.18.03,569 (33%)18,984 (24%)8,871 (18%)n/a6,882 (7%)
Gin v1.12.03,680 (43%)21,899 (29%)10,034 (10%)n/a6,450 (12%)
togo, 32 idle connections3,019 (50%)23,199 (3%)11,014 (2%)n/a6,472 (3%)
togo, as scaffolded (2 idle connections)627 (22%)1,351 (21%)722 (4%)n/a856 (5%)
Django 6.1.21,334 (10%)1,988 (32%)1,682 (2%)108 (2%)1,805 (1%)
Rails 8.1.41,774 (2%)2,405 (3%)1,885 (1%)n/a2,197 (12%)
Laravel 13.37309 (2%)324 (2%)240 (2%)n/a302 (3%)
FastAPI 0.143.31,012 (3%)1,334 (6%)658 (2%)n/a1,099 (7%)
Sinatra 4.2.13,524 (3%)5,313 (1%)3,588 (1%)n/a4,290 (3%)
uAdmin 0.10.2775 (16%)1,352 (6%)623 (3%)none786 (17%)

p95 latency

Milliseconds, lower is better.

Applistpetorderadminmix
Go baseline (chi, pgx, sqlc)63.01.94.0n/a6.6
tanGO v0.5.067.92.85.330.419.6
Fuego v0.18.060.12.45.9n/a10.6
Gin v1.12.062.92.44.1n/a17.3
togo, 32 idle connections71.62.44.3n/a10.0
togo, as scaffolded (2 idle connections)103.682.992.9n/a92.7
Django 6.1.226.815.522.4320.121.1
Rails 8.1.420.815.919.2n/a17.8
Laravel 13.37177.5174.4193.7n/a181.1
FastAPI 0.143.355.652.977.3n/a56.9
Sinatra 4.2.111.98.311.1n/a9.9
uAdmin 0.10.299.790.1101.5none100.2

Memory and cold start

AppPeak memory, MBCold start, ms
Go baseline (chi, pgx, sqlc)21108
tanGO v0.5.02257
Fuego v0.18.024107
Gin v1.12.016108
togo, 32 idle connections22213
togo, as scaffolded (2 idle connections)22211
Django 6.1.21041,389
Rails 8.1.42012,002
Laravel 13.37962,143
FastAPI 0.143.32531,946
Sinatra 4.2.185643
uAdmin 0.10.237215

Effort

What it took to build the same pet shop. Fewer lines is not a score.

AppAuthored linesAuthored tokensGenerated linesDependenciesImage, MB
Go baseline (chi, pgx, sqlc)5054,511277317
tanGO v0.5.03963,818165334
Fuego v0.18.04784,453277321
Gin v1.12.04934,353277332
togo6056,0985,7092559
Django 6.1.23122,809833204
Rails 8.1.41511,5193694624
Laravel 13.372532,3512,4393593
FastAPI 0.143.31832,20104280
Sinatra 4.2.11701,86706561
uAdmin 0.10.22942,56401134

Reading p95 on list

The Go apps have a typical list request of about 3.5 ms but a p95 of 60 to 70 ms, while Rails and Django, at a third of the throughput, show 21 and 27 ms. Every list request counts 10,000 rows on a PostgreSQL limited to 2 CPUs, and a Go app with a large connection pool runs many of those counts at once, so some requests wait far longer than others. Django and Rails run only a few queries at a time and queue the rest in order, which gives a narrower spread. On the plain Go baseline, list only, five runs each, the p95 was 62 and 61 ms with the default pool, 51 ms capped at 6 connections and 9 ms capped at 2, with throughput no lower. The tables use each framework's defaults, so they are unchanged: read p95 on list as a measure of concurrency, not of speed.

The two-connection default

database/sql keeps two idle connections by default, so under concurrent load a Go app closes and reopens PostgreSQL sessions on almost every request. togo as scaffolded lands near 1,350 requests per second on a single-pet read for this reason. tanGO v0.5.0 defaults to 32 idle connections; togo with DB_MAX_IDLE=32 is the second togo row.

The full method, the apps and the raw tables are in the benchmarks repository, including results.md.