Skip to content

PostgREST 14.14

Benchmark · Database-first · July 2026

Part of the PostgreSQL REST API Benchmark, July 2026 series.

At a glance

VersionPostgREST 14.14 (Haskell / GHC runtime)
PostgreSQL driverBuilt-in pool — db-pool = 100 (the default is 10)
Concurrency modelGHC green threads — no configuration
Lines of code12 (config only) — the lowest in the benchmark
Podiumsnone — 0 of 38 combinations
Sourcepostgrest-v14.14

The verdict in one sentence: twelve lines of configuration buy a complete REST API that keeps pace wherever the database does the work — and trails the field everywhere the server does.

Implementation

There is no application. The entire service is postgrest.conf; functions are called as /rpc/perf_test?_records=... instead of the /api/perf-test style the coded services use:

ini
ini
db-uri       = "postgres://testuser:testpass@postgres:5432/testdb"
db-schema    = "public"
db-anon-role = "testuser"

# Match the 100-connection pool every other service uses (default is only 10)
db-pool = 100

log-level = "crit"

The db-pool line is this round's fix: in January PostgREST ran its default of 10 connections while the field had ~100 — a silent 10× handicap on the resource every scenario contends for.

Results

Where config-only holds up

On the heaviest payloads, where connection availability and database time dominate, PostgREST sits in the top third of the field:

perf-test100 records500 records
50 VU169 (#7)35 (#8)
100 VU168 (#6)35 (#6)
200 VU168 (#6)35 (#5)

At 200 VU/500 records its #5 places it ahead of both Rust frameworks and all four JavaScript runtimes — proof that with a full-size pool, the Haskell runtime moves heavy rows as well as most hand-written services.

Where it trails

Everywhere the request itself is the work, PostgREST is #19 or #20 of 20:

ScenarioResult
perf-test, 1 record1,363 req/s at 50 VU falling to 1,237 at 200 VU (#20 at every concurrent level)
Minimal baseline6,986 req/s at 100 VU (#19) — only Django below it
Many parameters3,726 req/s at 50 VU (#19) — each _pN becomes a parsed, type-checked function argument
Large payload729 req/s at 25 VU/100 KB and 164 at 25 VU/500 KB (#20 in all four combos) — roughly half of the #19 result

Large payloads are the sore spot: the field clusters at 1,287–1,427 req/s on the 100 KB combos; PostgREST manages 727–729.

Latency

The 1-record tails tell the same story as the throughput table: p99 of 151 ms at 50 VU, 342 ms at 100 VU, and 755 ms at 200 VU — an order of magnitude above the leaders' 25–48 ms band at 50 VU. It was also the only service to break 1 s p99 on a large-payload combination (1,189 ms at 50 VU/500 KB). On the heavy perf-test combos, where it ranks well, its tails match the pack (2,515 ms at 200 VU/100 rec, mid-field).

Resource usage

Peak memoryAvg memoryAvg CPU
112 MB57 MB103.0%

Third-smallest peak footprint of all 20 services, behind only Swoole (44 MB) and Go (59 MB). A complete REST layer in 57 MB average is a respectable bill for zero application code.

Analysis

PostgREST's value is density, not speed. Twelve lines of configuration — the lines-of-code winner by a wide margin — produce six working endpoints plus a full REST surface (filtering, embedding, JWT auth) this benchmark never exercises. Every coded service on these pages spends 100–300 lines to match what one config file does. The trade is a fixed per-request tax that no configuration removes: last place in every small-request category, at every concurrency level.

But the tax is not inherent to the approach. NpgsqlRest, the other config-only competitor (21 lines), serves the same database-first idea at 15,549 req/s on the minimal baseline where PostgREST posts 6,986, and 2,615 req/s on 1-record perf-test where PostgREST posts 1,322 — roughly 2× on both, from a config file of comparable size. Database-first is not the bottleneck; this particular request pipeline is.

January → July movement: the db-pool 10 → 100 fix is the headline change, and its signature is visible in the heavy combinations, where PostgREST now holds #5–#8 instead of queueing on a starved pool; the small-request categories stayed at the bottom, as in January. Rankings only — the methodology changed too much for absolute comparisons.

Explore on GitHub

Everything this page claims can be checked against the running code and the raw output:


Series: Introduction · Overall Analysis · Raw Results

Next: NpgsqlRest Deep Dive →

Comments