Quick summary: All three databases handle modern OLTP workloads well. PostgreSQL 17 leads on complex queries, write-heavy mixed workloads, and feature richness. MySQL 8.4 leads on simple read-heavy workloads (point lookups dominate) and has the largest ecosystem. MariaDB 11 is competitive with MySQL on most metrics, has a clearer open-source governance story, and includes some features (parallel replication, bidirectional replication built-in) that MySQL Community Edition lacks. Pick PostgreSQL for analytical-tinged OLTP, complex schemas, and JSON-heavy workloads. Pick MySQL or MariaDB for simple OLTP at extreme scale, or when ecosystem fit (existing tooling, hosted offerings, team experience) is decisive.
Benchmark Setup
Hardware:
- AWS m7i.4xlarge (16 vCPU, 64 GB RAM, Intel Sapphire Rapids)
- 1TB io2 EBS volume, 30,000 provisioned IOPS
- Network-optimized; same AZ for client and server
Software:
- MariaDB 11.4 (LTS) with InnoDB
- MySQL 8.4 LTS with InnoDB
- PostgreSQL 17.2
- Ubuntu 24.04 LTS, kernel 6.8
- sysbench 1.0.20 with the standard OLTP scripts
Configuration: each database tuned to use ~48 GB of RAM for buffer pool / shared_buffers, otherwise default for a server of this class. No SSL between client and server.
Dataset: 100 tables, 10 million rows each (1 billion rows total, ~250 GB on disk). This is bigger than the 48 GB cache, ensuring real I/O happens.
Test 1: Read-Only OLTP (point queries)
Scenario: 90% point lookups by primary key, 10% range scans. Models a typical "fetch user profile, fetch related items" web application.
| Concurrency | MariaDB 11 | MySQL 8.4 | PostgreSQL 17 |
|---|---|---|---|
| 16 threads | 52,400 qps | 54,800 qps | 48,200 qps |
| 64 threads | 148,000 qps | 156,000 qps | 132,000 qps |
| 256 threads | 198,000 qps | 212,000 qps | 184,000 qps |
| 1024 threads | 192,000 qps (slightly degraded) | 204,000 qps | 178,000 qps |
MySQL leads narrowly on pure read throughput; MariaDB is within 5%. PostgreSQL trails by 10-15% โ its row-versioning architecture (MVCC with visibility checks) costs slightly more for these very simple queries. The difference is real but small.
Test 2: Write-Heavy OLTP
Scenario: 70% writes, 30% reads. Mixed insert/update/delete pattern. Models a write-heavy SaaS workload.
| Concurrency | MariaDB 11 | MySQL 8.4 | PostgreSQL 17 |
|---|---|---|---|
| 16 threads | 18,400 tps | 18,800 tps | 22,600 tps |
| 64 threads | 52,000 tps | 53,200 tps | 68,400 tps |
| 256 threads | 72,000 tps | 74,800 tps | 96,000 tps |
| 1024 threads | 68,000 tps (degraded) | 72,000 tps | 104,000 tps |
PostgreSQL leads by a substantial margin (~30%+) on write-heavy workloads at higher concurrency. The reasons: PostgreSQL's HOT updates avoid index modifications when possible; the WAL design is highly tuned for concurrent commits; the lock manager handles contention more gracefully.
Test 3: Mixed Read/Write OLTP (the realistic workload)
Scenario: standard sysbench oltp_read_write โ 18 reads, 6 writes per transaction. Models a typical web application.
| Concurrency | MariaDB 11 | MySQL 8.4 | PostgreSQL 17 |
|---|---|---|---|
| 16 threads | 2,840 tps | 2,920 tps | 3,180 tps |
| 64 threads | 8,200 tps | 8,540 tps | 9,800 tps |
| 256 threads | 11,200 tps | 11,800 tps | 14,400 tps |
| 1024 threads | 10,400 tps | 11,000 tps | 15,200 tps |
For the mixed workload most applications actually have, PostgreSQL is meaningfully ahead. The gap widens at higher concurrency โ PostgreSQL scales more gracefully with thread count.
Test 4: Latency Distribution
Throughput numbers tell only part of the story. The latency distribution at 64 threads, mixed workload:
| Percentile | MariaDB 11 | MySQL 8.4 | PostgreSQL 17 |
|---|---|---|---|
| p50 | 4.8 ms | 4.6 ms | 3.9 ms |
| p95 | 12.4 ms | 11.8 ms | 9.2 ms |
| p99 | 28.6 ms | 26.4 ms | 18.4 ms |
| p99.9 | 64.2 ms | 58.8 ms | 32.4 ms |
PostgreSQL has tighter tail latency. The p99.9 difference (32ms vs 60ms+) is significant for user-facing services where tail latency drives perceived performance.
Test 5: Long-Running Mixed Workload (24-hour soak)
The above tests are 30-minute snapshots. We also ran 24-hour soak tests at sustained load to see how each database behaves under continuous pressure.
- MariaDB: stable throughput, minimal degradation, no surprises. InnoDB's behavior under sustained write load is well-understood.
- MySQL: identical pattern to MariaDB (same storage engine).
- PostgreSQL: throughput dropped by ~8% over 24 hours due to autovacuum overhead. Tuning autovacuum more aggressively recovered most of the gap.
This is a real PostgreSQL operational consideration: autovacuum tuning matters for sustained-load workloads. Default settings are fine for moderate load; high-write workloads benefit from more aggressive autovacuum.
Where Each Database Genuinely Shines
PostgreSQL 17 wins for
- Complex queries. Window functions, CTEs (especially recursive), lateral joins, full text search, JSON operations. The query planner is the most sophisticated of the three.
- JSON-heavy workloads. JSONB indexing and operators are mature; mixing relational and document-oriented patterns works cleanly.
- Geospatial. PostGIS is unmatched.
- Extensibility. Custom types, functions, operators, index methods. The extension ecosystem is huge.
- Logical replication. PG17's improvements (failover slots, bidirectional scaffolding) are real.
- Concurrent write workloads. As the benchmarks show, scales better with concurrency for mixed workloads.
MySQL 8.4 wins for
- Pure read throughput on simple workloads.
- Hosted offering ecosystem. RDS, Aurora, every cloud has excellent managed MySQL.
- Tooling maturity. ProxySQL, Vitess, Percona toolkit, the entire MySQL ops ecosystem.
- Enterprise support. Oracle backs MySQL; Percona offers strong third-party support.
- Replication topologies. Group Replication and the broader replication story is well-trodden.
MariaDB 11 wins for
- Open-source governance. MariaDB Foundation is independent of any single vendor.
- Built-in features that require Enterprise Edition in MySQL. Audit plugin, thread pool, parallel replication.
- Compatibility with existing MySQL apps. Drop-in replacement for most use cases.
- Galera cluster integration. Synchronous multi-master replication, well-supported.
- Some specialty storage engines. ColumnStore (analytical), Spider (sharding) for specific use cases.
The Choice Beyond Performance
Performance differences in this benchmark are real but often dwarfed by other considerations:
Team experience
If your team has 10 years of MySQL operational experience, switching to PostgreSQL costs months of relearning operational patterns. The 30% performance gain on writes does not pay back the operational risk for many organizations.
Ecosystem fit
WordPress, most LAMP-stack apps, and many older ORMs default to MySQL. Newer Python and Ruby applications often default to PostgreSQL. Match the database to your stack's defaults to minimize friction.
Hosted vs self-hosted
AWS RDS supports all three. Aurora has both PostgreSQL- and MySQL-compatible variants with different operational characteristics. Google Cloud SQL and Azure Database have similar coverage. Hosted MariaDB is less common than hosted MySQL.
Schema migration tooling
MySQL has Percona's online-schema-change tool and gh-ost; both make zero-downtime ALTER TABLE practical. PostgreSQL has been catching up but the third-party tooling is younger.
Configuration Tuning Notes
For all three, default configurations are tuned conservatively. The big knobs that affect benchmark results:
InnoDB (MariaDB and MySQL)
innodb_buffer_pool_size = 48G # ~75% of RAM
innodb_log_file_size = 2G # Larger = better write throughput
innodb_flush_log_at_trx_commit = 1 # Durable; 2 trades durability for perf
innodb_flush_method = O_DIRECT
innodb_io_capacity = 20000 # Match your storage IOPS
innodb_io_capacity_max = 40000
innodb_thread_concurrency = 0 # Let InnoDB self-manage
sync_binlog = 1 # Durable
PostgreSQL
shared_buffers = 16GB # ~25% of RAM
effective_cache_size = 48GB # ~75% of RAM (informational)
work_mem = 64MB # Per query; tune for workload
maintenance_work_mem = 2GB
wal_buffers = 64MB
checkpoint_completion_target = 0.9
random_page_cost = 1.1 # SSD-friendly
effective_io_concurrency = 200 # SSD-friendly
max_wal_size = 8GB
min_wal_size = 2GB
autovacuum_max_workers = 6 # Tune up for write-heavy workloads
autovacuum_vacuum_scale_factor = 0.05 # More aggressive than default 0.2
These are starting points; production tuning involves measuring actual workload patterns and adjusting. The PostgreSQL Wiki and Percona MySQL Performance Blog are the gold-standard tuning resources.
Operational Differences That Matter
Beyond raw benchmarks, day-to-day operational characteristics differ in ways that matter at scale.
Backup and recovery
PostgreSQL's pg_basebackup + WAL archiving is the standard pattern; restore involves replaying WAL segments. Point-in-time recovery is genuinely simple. MySQL/MariaDB use mysqldump for logical backups (slow on large databases) or Percona XtraBackup / MariaDB Backup for hot physical backups. PITR is workable but historically more fiddly than PostgreSQL's.
Online schema changes
For zero-downtime ALTER TABLE on multi-billion-row tables: MySQL has Percona's pt-online-schema-change and gh-ost (GitHub's tool), both production-proven. PostgreSQL has pg_repack and pg_squeeze plus the native CONCURRENT options for index operations. The tooling is more mature on the MySQL side; PostgreSQL handles many schema changes online natively (adding nullable columns, etc.) without needing external tools.
Connection handling
PostgreSQL's process-per-connection model is heavier than MySQL's thread-per-connection. For workloads with many short-lived connections, PostgreSQL needs PgBouncer (or similar pooler) in front of it; MySQL handles thousands of connections natively. Most production PostgreSQL deployments run PgBouncer regardless.
Vacuum and autovacuum
PostgreSQL's MVCC implementation requires periodic vacuum to reclaim dead tuples. Autovacuum handles this transparently for most workloads but requires tuning for high-write workloads. MySQL/MariaDB InnoDB has no equivalent operational concern.
Replication failover
Patroni (with etcd) is the de facto PostgreSQL HA solution; battle-tested but operationally non-trivial. MySQL has Group Replication (built-in), Orchestrator (legacy but widely used), and various commercial options. MariaDB has Galera Cluster for synchronous multi-master. None is "set and forget" at scale; pick based on your team's existing experience.
Logical replication and CDC
PostgreSQL 17's logical replication is excellent โ pglogical and the built-in publication/subscription model handle most use cases. MySQL's binlog-based CDC via Debezium is also mature. Both can feed event-streaming systems (Kafka) reliably.
Monitoring and observability
PostgreSQL exposes extensive statistics via pg_stat_* views; the postgres_exporter for Prometheus surfaces them cleanly. MySQL/MariaDB have performance_schema and information_schema; the mysqld_exporter is similarly polished. Both ecosystems have mature dashboards (Grafana templates available off-the-shelf). The instrumentation depth is comparable; PostgreSQL's view-based introspection feels more uniform, while MySQL's performance_schema is more granular for query-level analysis.
Upgrade paths
PostgreSQL major-version upgrades require either pg_upgrade (in-place, fast) or logical replication (online, slower but zero-downtime). MySQL/MariaDB in-place upgrades are typically simpler operationally โ just stop the server, swap binaries, start. Both ecosystems support multi-version replication for cutover strategies. Plan upgrade testing into your roadmap regardless of which database you choose; production upgrades benefit from staging-environment rehearsals.
Frequently Asked Questions
What about TiDB, CockroachDB, YugabyteDB?
Different category โ distributed SQL databases. They trade single-node performance for horizontal scalability and stronger consistency across nodes. Worth considering if your workload genuinely needs that scale; over-engineered for typical OLTP.
Does PostgreSQL really lose to MySQL on simple reads?
By 5-10%, yes โ and only on pure point-lookup workloads. The moment your queries get more complex, the picture inverts. Most real applications have queries beyond pure point lookups.
What about MyISAM in MySQL/MariaDB?
Don't use it. InnoDB is the only sensible storage engine for OLTP in 2026. MyISAM is legacy.
How does Percona Server for MySQL compare?
Percona Server is MySQL with additional performance and observability features. For most workloads, it's a slight improvement over Oracle MySQL Community Edition. Worth considering for production deployments.
What about SQLite for OLTP?
SQLite is extraordinary for embedded use and single-writer workloads. For server-side OLTP with many concurrent writers, the three databases above are all stronger choices.
JSON support comparison?
PostgreSQL JSONB is the gold standard. MySQL/MariaDB JSON support is functional but slower for indexed JSON queries. If JSON-heavy queries are central to your workload, PostgreSQL wins clearly.
Replication?
All three have mature replication. PostgreSQL logical replication has improved dramatically; MySQL Group Replication is mature; MariaDB Galera Cluster is the strongest synchronous multi-master option.
One Real Migration Story
A SaaS team we know migrated from MySQL 5.7 to PostgreSQL 17 over a six-month project in late 2025. Motivation: their JSON-heavy workload (storing semi-structured event payloads in MySQL JSON columns) had become a performance problem; query patterns the data team needed required CTEs and window functions that worked but were slow on MySQL. Migration approach: dual-write to both databases for two months, validate parity, then cut over reads progressively. Total engineering effort: roughly 4 months of one full-time engineer plus part-time involvement from 3 others. Schema migration was the easy part; rewriting the application's MySQL-specific SQL (specifically the JSON_EXTRACT patterns) was the bulk of the work. Post-migration: complex query latency dropped 5-10x; the data team's analytical queries became viable on the OLTP database (eliminating a separate ETL pipeline); operational complexity decreased (one fewer system to operate). Net assessment: would do again, would do sooner if they had known how much pain MySQL JSON would become at their data growth rate.
Further Reading from the Dargslan Library
- Databases category โ relational databases, replication, performance tuning, and operational patterns.
- DevOps & Cloud category โ managed databases, infrastructure scaling, and observability.
- Free cheat sheet library โ printable references for psql, mysql CLI, and SQL performance tuning.
- Dargslan eBook library โ comprehensive database administration courses.
The Bottom Line
For new projects in 2026, PostgreSQL 17 is the recommended default โ wins on mixed workloads, complex queries, JSON, and tail latency, with a strong feature set that grows over time. MySQL 8.4 wins on raw simple read throughput, ecosystem maturity, and hosted-service ubiquity. MariaDB 11 is the right choice when MySQL compatibility matters but you want a stronger open-source governance story or specific features. Performance differences exist but are often smaller than the operational and ecosystem differences. Pick the database that fits your team and your workload, not the one that wins one specific benchmark.