Performance
Transactional throughput and latency against Postgres, analytical results on ClickBench, and the machine and methodology behind every number.
In the 2026-08-31 benchmark campaign, Postgres had 1.8–2.6× the point-read throughput and 1.2–3.6× the durable single-row update throughput of Lakefront’s HTTP node. Lakefront’s hot ClickBench total was approximately 0.5% higher than native DuckDB.
The tables below report throughput and latency for transactional workloads against Postgres, and analytical query times against native DuckDB.
Machine and setup
Every number on this page comes from one campaign, run 2026-08-31:
| CPU | Apple M4 Pro |
| Memory | 48 GB |
| OS | macOS 26.6.2 |
| Postgres | 17, in Docker (OrbStack), reached over the host port map |
| Lakefront | this repo at the commit publishing these numbers, writePath: "wal" |
Both engines are reached through a Docker port mapping from the host running the client. Running pgbench inside the container instead uses a loopback connection; in this campaign, that increased Postgres select-only throughput by 7–19×. The harness warns when it uses that configuration.
Lakefront acknowledges writes after a group-committed, fsynced Postgres commit. The comparison uses Postgres with synchronous_commit=on to match that durability requirement. The sync=off row is included as a reference with weaker durability.
Transactional performance
pgbench’s own builtin workloads at scale 1 (100,000 rows). Latencies are per-operation.
Compare Postgres over TCP with Lakefront’s HTTP node: both include a network hop. Embedded Lakefront results measure in-process execution and exclude the HTTP and network overhead.
Multi-statement transactions had approximately half Postgres’s throughput, even with Lakefront measured embedded.
Point reads
pgbench select-only, against Postgres over TCP and a Lakefront server node over HTTP. The replica is warm, ART-indexed on id.
| Clients | System | tps | p50 | p95 |
|---|---|---|---|---|
| 1 | Postgres | 14,006 | 0.071 ms | |
| 1 | Lakefront HTTP | 6,479 | 0.139 ms | 0.219 ms |
| 8 | Postgres | 44,855 | 0.178 ms | |
| 8 | Lakefront HTTP | 25,023 | 0.297 ms | 0.435 ms |
| 32 | Postgres | 72,439 | 0.442 ms | |
| 32 | Lakefront HTTP | 28,116 | 1.045 ms | 1.667 ms |
Postgres had 1.8–2.6× the point-read throughput of a Lakefront HTTP node. Lakefront’s p50 latency was 0.297 ms at 8 clients and 1.045 ms at 32. Its request path includes HTTP and JSON handling.
Embedded reads measured 0.079 ms p50 at 1 client and 0.412 ms at 32 (11,783 and 71,565 tps). These results show the cost of querying a local DuckDB replica without the HTTP serving layer.
Single-row updates
A bare update, no transaction wrapper on either side.
| Clients | System | tps | p50 | p95 |
|---|---|---|---|---|
| 1 | Postgres sync=on | 1,282 | 0.780 ms | |
| 1 | Lakefront HTTP | 357 | 1.432 ms | 5.981 ms |
| 8 | Postgres sync=on | 2,035 | 3.931 ms | |
| 8 | Lakefront HTTP | 1,673 | 2.542 ms | 10.189 ms |
| 8 | Postgres sync=off (weaker durability) | 43,747 | 0.183 ms |
At one client, Postgres had 3.6× Lakefront’s update throughput. Each Lakefront write includes request handling and a WAL append committed to Postgres before acknowledgment. Flushing records into the lake happens later, outside the request path.
At eight clients the throughput gap narrowed to 1.2×. Group commit combines concurrent writes into shared Postgres transactions, amortizing the fsync cost.
Where a write spends its time
For one durable write, in order:
- HTTP request parsing and contract validation on the node.
- A per-board advisory lock and the WAL append, as a single plpgsql call: one round trip, one fsynced Postgres commit.
- The ack returns. The write is durable at this point.
- Later, off the request path: the flusher drains WAL records into Parquet, and replicas sync so reads observe the change.
The caller waits for the Postgres commit. Lake flushing and replica synchronization proceed independently afterward.
Analytical performance
The full ClickBench suite: one 99,997,497-row web-analytics table, 43 scan/aggregation queries, run three times each. “Hot” is the best repeat run; “cold” is the first touch.
| System | Queries | Hot total | Hot p50 | Hot p95 | Cold total |
|---|---|---|---|---|---|
| Lakefront (board over a warm replica) | 43/43 | 10.22 s | 118 ms | 713 ms | 15.31 s |
| DuckDB native (same machine, same data) | 43/43 | 10.17 s | 154 ms | 617 ms | 14.44 s |
Lakefront’s hot total was 10.22 s versus 10.17 s for native DuckDB, a difference of approximately 0.5%. Queries execute directly in the warm DuckDB replica.
Re-measuring
These results come from one campaign on one machine. Network path, disk, and tuning affect the measurements. The benchmarking guide covers running the harnesses, including host-side pgbench and both ClickBench variants.