How to Set PostgreSQL Transaction Isolation Levels
In PostgreSQL, a transaction groups database statements that commit or roll back together. Its isolation level controls which changes from other transactions…
When you choose a database for a service, speed matters only if it helps the service handle the requests it receives. MySQL and PostgreSQL can each perform well, but which is faster depends on the workload and your response-time goals. Your queries, data, hardware, and configuration all shape the result.
A benchmark reports PostgreSQL ahead of MySQL on one transactional workload, but it tested older versions and default settings. That result does not establish a universal winner. To compare the databases for your use case, measure both with representative data and traffic, and compare both the amount of work they complete and how long requests take.
Throughput measures how much work a database completes over time. Latency measures how long a request takes. A database can achieve high throughput while still responding slowly to some requests, so compare both measures.
Latency percentiles show how response times vary. The median, or p50, marks the point at which half of requests finish faster and half finish slower. The p99 marks a high-end point in the response-time distribution. For a service with strict response-time targets, p99 can reveal slow requests that an average hides.
The useful question is whether either database meets your throughput and latency targets with your workload, including when many requests run at the same time. A test dominated by short transactions answers a different question from one dominated by large scans or aggregations.
The OLTP.dev benchmark reports these results for a transactional test designed around order processing:
| Database and version | Throughput | Median latency (p50) | p99 latency |
|---|---|---|---|
| PostgreSQL 17.0 | 1,312 transactions per second | 11.8 ms | 42.8 ms |
| MySQL 9.0 | 1,156 transactions per second | 13.2 ms | 48.3 ms |
In this test, PostgreSQL completed about 13.5% more transactions per second, and its reported p99 latency was about 11.4% lower. Those percentages are calculated from the benchmark’s reported figures.
The result applies to the tested versions and setup. The benchmark methodology describes identical GitHub-hosted runners. Each had four CPU cores and 16 GB of memory, plus SSD storage. The test used default configurations, a five-minute warm-up, and a 30-minute measurement period. Its workload included transactions such as creating orders, recording payments, checking order status, and updating inventory.
That comparison does not settle which database is faster in 2026. It tested PostgreSQL 17.0 against MySQL 9.0, rather than PostgreSQL 18 against the MySQL 9.7 version documented in the research brief. The test also does not represent every workload or deployment, and its authors caution that the small runners do not predict production performance. Treat the figures as evidence about one test, not as a general performance ranking.
A database’s query plan describes how it will find and combine the requested rows. When a query runs slowly, inspect that plan before attributing the delay to the database engine. A slow query can result from an inefficient scan or a poor join order. It can also result from inaccurate statistics, which summarize the data and help the database choose how to run the query, or from an index that does not match the query. An index is a structure that helps the database find rows.
PostgreSQL’s EXPLAIN shows the selected plan, while EXPLAIN ANALYZE also runs the query and reports actual execution details. MySQL’s EXPLAIN shows how its optimizer plans to process a statement, including table join order. PostgreSQL warns that EXPLAIN ANALYZE executes the statement, so take care when analyzing a statement that changes data. Compare plans and measured query times on the same schema and data distribution.
Indexes help a database find rows without scanning an entire table, but they take storage and add work when the database inserts, updates, or deletes rows. MySQL’s index guidance describes this trade-off. Add or remove indexes based on queries you have measured, then check whether the optimizer uses them.
Memory and storage also affect results. MySQL’s InnoDB engine uses a buffer pool to cache data and indexes, making its buffer-pool settings a relevant area to examine for read-heavy workloads. PostgreSQL’s performance guidance likewise covers planning, statistics, and configuration. Before comparing speeds, give each database an appropriate configuration and record whether you tested defaults or tuned settings.
The databases also provide different mechanisms worth testing for particular queries. PostgreSQL can use multiple CPUs for eligible parts of some queries. Its parallel-query documentation describes large scans that return relatively few rows as potential candidates, while noting that parallel execution does not help every query. PostgreSQL 18’s release announcement reported up to three times faster reads from storage in some cases; that project claim is not a head-to-head comparison with MySQL and does not predict a typical application’s gains.
Run both databases with the versions and deployment options you are considering. Keep CPU, memory, storage, network placement, and client location comparable. Use representative row counts and patterns of data values, along with representative read and write patterns and numbers of requests running at the same time. If you test a managed database service, include its configuration and network path in the comparison.
Measure throughput alongside p50, p95, and p99 latency. Include the queries that matter most to the service, and record resource use so you can see whether a result came with higher CPU or memory consumption. Repeat runs and report variation rather than choosing the best run as if it were typical.
Test defaults and tuned configurations separately. A tuned result helps compare performance after reasonable configuration work; a default result shows how the databases behave without that work. Document the settings so another operator can reproduce the comparison. If one query performs poorly, inspect its plan, actual row counts, statistics, and index use before drawing a conclusion about the engine.
A migration decision also needs to account for the work beyond query speed. The OLTP.dev methodology excludes the time to switch to another database after a failure and recover, the delay when data is copied between regions, operational complexity, and cost per transaction. A benchmark that omits those factors cannot determine which database will be less costly or easier to operate for your service.
Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.
Take a look at vroni.com