Postgres 19 Beta Shows INSERTs Up to 30% Faster in Independent OLTP Benchmark
A self-funded benchmark by consultant Kaarel Moppel compares Postgres 18.6 and Betas 3 and 4 of version 19 under real OLTP workloads. The average gain is modest, but it hides a detail that matters to anyone running heavy write workloads on the database.
PostgreSQL's annual release cycle tends to come with an extra dose of anxiety this year. According to consultant Kaarel Moppel, in a post published on Planet PostgreSQL, the volume of code changes in version 19 is visibly larger than usual: a git diff --shortstat against v18 shows 15% more files changed, 38% more insertions, and 75% more line removals. There was also a wave of reverts before the betas were cut, which took away some of that "this will be smooth as always" feeling.
To test whether this turbulence affected what he calls Postgres's "bread and butter", OLTP workload performance (record-keeping transactional systems, the type of workload that underpins most production applications), Moppel paid out of pocket for a round of cloud testing. He ran two distinct workloads across varied hardware, comparing the stable v18.6 against Betas 3 and 4 of v19, in a mix he humorously dubbed "version 3.5".
How the Test Was Set Up
The scope isn't small: around 800 hours of execution, equivalent to 33 days of accumulated runtime, spread across instances ranging from 4 to 96 vCPUs (including the m7gd, m8id, c5d, and c7gd types) running Ubuntu 26.04 Server and Debian 13, two-thirds on AWS and one-third on Hetzner. The dataset was sized to fit in memory or require little disk access, and measurement used pg_stat_statements to capture the execution time of each query individually.
Four workloads were tested: key-based reads (pgbench --select-only), batch reads by aid range, key-based updates (pgbench --skip-some-updates), and a TPCC-like test variant adapted to run on top of pgbench, a workload that simulates a more realistic scenario with more tables and indexes.
A few configuration details deserve the attention of anyone who administers real-world databases:
autovacuumwas disabled during the tests, to isolate the engine's pure effect without interference from vacuum running in parallel;- the
fillfactorofpgbenchwas fixed at 80%, simulating a heap that has already accumulated "holes" from real-world use, rather than freshly created, compacted tables; jitwas kept off, which is already the default behavior in v19 (a configuration change worth noting separately);- parameters such as
random_page_cost,effective_io_concurrency,wal_compression, andtrack_io_timingreceived best-practice adjustments proportional to each instance's hardware.
The Numbers: Real but Uneven Gains
In aggregate, summing all workloads, partitioning variables, query protocol, and commit mode (synchronous or asynchronous), the total execution time of the tests dropped about 3% in v19 relative to v18.6. That's a modest but positive number, and Moppel himself sums up the result in a direct sentence:
You shouldn't worry too much about PostgreSQL's bread-and-butter OLTP capabilities with release 19!
Kaarel Moppel, consultant and author of the benchmark
The most interesting data point, though, shows up when you look operation by operation instead of at the aggregate. The average improvement per statement type (SELECT, INSERT, UPDATE) reached 7%, more than double the gain measured in total test duration. Moppel attributes the difference to something every DBA who has hunted bottlenecks knows: pg_stat_statements measures query execution time, but doesn't fully capture time spent on session, transaction, and lock management. Part of the real gain may be hidden exactly there.
Broken down by operation type, the picture looks like this:
| Operation | Result in v19 Beta vs. v18.6 |
|---|---|
| SELECT (key-based and batch) | slightly faster |
INSERT (pgbench) | 25% to 30% faster |
| Key-based UPDATE | same or slightly slower |
| TPCC-like (full workload) | larger gain than standard pgbench |
The jump in INSERTs was, in the author's own words, the test's only real surprise, and he himself admits he hasn't yet investigated the root cause. For anyone running heavy ingestion workloads, such as event pipelines, table-persisted queues, or audit systems that write a lot and read little, this is the number that deserves attention before any other.
What This Gain Doesn't Solve
Key-based UPDATEs, a typical operation in classic transactional systems (updating a balance, order status, inventory), didn't share in the gain. They came out statistically tied or slightly worse on v19. This matters because it's exactly the type of workload where row locking, MVCC, and dead tuple generation (the fuel for autovacuum) weigh the most, and it's also the workload most sensitive to subtle regressions.
It's worth remembering, and the author himself insists on this, that autovacuum was turned off throughout the entire test. In production, repeated UPDATEs on the same row generate bloat constantly, and vacuum behavior (which wasn't measured here) can weigh as much or more than the raw gain or loss of each operation. A benchmark that isolates the variable is methodologically sound, but it doesn't replace testing your own workload against the application's real schema.
Cloud Noise: The Warning Every VM Benchmark Carries
Moppel is explicit about the difficulty of measuring performance in shared cloud environments. He reports seeing more jitter (variation in results between identical runs) than in previous tests, to the point of discarding outliers and moving part of the tests to dedicated "metal" instances and to a second provider (Hetzner), precisely to reduce the influence of noisy neighbors, NUMA, CPU power states, and operating system cache.
For anyone planning to reproduce this kind of test internally before deciding on a migration, here's the practical lesson: short runs aren't enough, and comparing numbers from a public cloud without controlling for physical hardware can skew the conclusion in either direction.
What Changes for Today's Database Administrators
v19 is still in Beta (the test uses Betas 3 and 4, with no general availability date set yet), so there's no migration decision to make right now. The value of this material lies elsewhere: it's one of the few independent signals, outside the project's official announcement cycle, that the significant increase in internal changes in v19 hasn't compromised the database's most critical path, which is sustaining small, frequent transactions without degradation.
For architectures with high INSERT write volume, the reported gain justifies setting aside a staging environment as soon as v19 leaves Beta to measure the same behavior against the real schema, with autovacuum on and a fillfactor matching the production table. For UPDATE-dominated workloads, the recommendation is not to expect an automatic gain and to treat the migration as performance-neutral until proven otherwise.
Moppel closes the post by advocating for reviving the Postgres Performance Farm community project, an initiative that once existed to automatically publish benchmark numbers for each Beta and is now inactive. The absence of such a dashboard is, in practice, the reason why individual tests like this one remain the main source of concrete performance data before the official release.
Translated from the Brazilian Portuguese original · Read the original
PostgreSQL's row-level security error hides six different causes
A survey tested eleven types of writes against five RLS policy configurations in PostgreSQL 17.11 and showed that the same error message covers quite distinct causes, from a missing tenant to a RETURNING clause that reads before writing.