Databases · Updated 2026-05-24

Postgres vs MySQL

Postgres has the deeper feature set and the more honest engine. MySQL has the broader ecosystem and the easier replication story. New projects without strong reasons should default to Postgres.

PLATE — DATABASE ENGINESPOSTGRESJSONBGINCTEsSSItsvecPostGISpgvectorCitusTimescale+ 250vsMYSQLInnoDB engineGroup Replic.binlogreplicaFEATURE BREADTH · OPERATIONAL BREADTH
PostgreSQL
The most advanced open-source relational database.
Since
1996
By
PostgreSQL Global Development Group
License
PostgreSQL License (BSD-like)
www.postgresql.org ↗
MySQL
The world’s most widely deployed open-source relational database.
Since
1995
By
Oracle (originally MySQL AB)
License
GPL v2 / commercial
www.mysql.com ↗

Both are mature, free, and run serious workloads at every scale. They differ in shape, not in capability. Postgres is denser with features and type safety; MySQL is denser with operational lore and library support. The right pick usually comes down to which density a team already lives inside.

Quick takes

If you're…

  • You need CHECK constraints, custom types, or array columns Postgres Native in Postgres; bolted on or missing in MySQL.
  • You need JSON querying with real indexes on properties Postgres JSONB with GIN indexes is faster at scale than MySQL JSON.
  • You run a read-heavy WordPress, phpBB, or Magento app MySQL These stacks were built MySQL-first. The ecosystem assumes it.
  • You want logical replication with point-in-time recovery Postgres Postgres ships both logical and physical replication; MySQL binlog is more brittle.
  • You need full-text search across many languages Postgres tsvector handles 20+ language stemmers. MySQL FULLTEXT is basic English.
  • Your team has long-running MySQL ops experience MySQL Familiarity matters more than feature parity for most teams.
  • You need geospatial queries Postgres PostGIS is the reference implementation; MySQL spatial is rarely used.
  • You want the cheapest possible managed instance at micro scale MySQL MySQL on RDS or Cloud SQL is consistently a touch cheaper at tiny sizes.
Decision wizard

A few questions, a verdict.

Q1

How would you describe your primary workload?

Q2

How important is strict ACID & schema correctness?

Q3

Will you need JSON-as-primary-storage or complex types?

Q4

Team familiarity?

At a glance

The scorecard.

Dimension
Postgres
MySQL
Edge
Full, single engine
Full on InnoDB; MyISAM is not
Postgres
Cost-based, mature
Heuristic with cost
Postgres
Logical and physical; failover BYO
Native primary-replica + Group Replication
MySQL
Extensibility features
250+ extensions, custom types
Pluggable engines, thin extensions
Postgres
JSON support features
JSONB + GIN indexes
JSON type, slower at scale
Postgres
MVCC + vacuum
MVCC + undo logs
tie
tsvector + 20 languages
Basic FULLTEXT, English-flavored
Postgres
Many specialists
Strong managed, fewer specialists
Postgres
In depth

Dimension by dimension.

core

ACID compliance

edge: Postgres
Postgres

Full ACID with serializable isolation via Serializable Snapshot Isolation. The default isolation level is Read Committed; serializable is one setting away. Constraints are enforced at the engine level.

MySQL

Full ACID on the InnoDB engine, which is the default since 5.5. The older MyISAM engine, still around for legacy schemas, is non-transactional and silently ignores foreign keys. That has eaten production data more than once.

core

Query optimizer

edge: Postgres
Postgres

Cost-based and statistics-driven. EXPLAIN ANALYZE produces detailed plans you can trust. The planner handles CTEs, window functions, and recursive queries without manual hints.

MySQL

Heuristic with some cost-based elements. Multi-table joins sometimes need optimizer hints to produce sensible plans. Improved in 8.0 but still trails Postgres on the harder cases.

ops

Replication

edge: MySQL
Postgres

WAL streaming for hot standbys, plus logical replication since version 10 for selective table sync. Multi-master needs external tooling like BDR or Citus. Failover is manual unless Patroni or Stolon is wired in.

MySQL

Native primary-replica via binlog. Group Replication and InnoDB Cluster ship in-box for multi-master and automatic failover. This is the one area where MySQL is operationally simpler.

features

Extensibility

edge: Postgres
Postgres

Custom types, operators, aggregate functions, embedded languages (Python, R, V8), and 250-plus extensions on PGXN, including pgvector, PostGIS, TimescaleDB, Citus, and pg_partman.

MySQL

Plugin architecture exists, ecosystem is thinner. Storage engines are pluggable (InnoDB, MyISAM, MyRocks, MEMORY) but rarely changed in production. Vector search and similar extensions trail Postgres by years.

features

JSON support

edge: Postgres
Postgres

JSONB stores parsed binary. GIN indexes on JSONB make property lookups fast. A hybrid relational and document schema can live in one table and one query.

MySQL

JSON type since 5.7. Storage is text-shaped. Functional indexes work but querying is slower at scale than JSONB. Fine for occasional JSON columns; not for JSON as primary storage.

core

Concurrency model

tie
Postgres

MVCC with per-row versioning. Long-running readers do not block writers. Vacuum is the trade-off: dead rows accumulate and autovacuum has to manage them. Tuning matters at high write rates.

MySQL

MVCC on InnoDB with similar guarantees in practice. Undo logs grow instead of dead rows; the purge thread cleans them. Slightly easier steady-state ops for write-heavy workloads.

features

Full-text search

edge: Postgres
Postgres

tsvector and tsquery, with stemmers for 20-plus languages, configurable dictionaries, ranking functions, GIN and GIST indexes. Good enough that apps under roughly 10M documents rarely need a dedicated search engine.

MySQL

FULLTEXT indexes on InnoDB (5.7+) and MyISAM. Basic English stemmer, limited stop-word configuration, no ranking customisation. Useful as a starter; teams outgrow it.

ecosystem

Hosted offerings

edge: Postgres
Postgres

AWS RDS and Aurora, GCP Cloud SQL, Azure Database, plus specialists like Neon, Supabase, Crunchy, Aiven, and Timescale Cloud. Aurora Postgres uses a different storage layer underneath.

MySQL

AWS RDS and Aurora, GCP Cloud SQL, Azure Database, PlanetScale (Vitess-based), Aiven. Strong managed-tier presence but fewer specialist providers.

Benchmark

Read-heavy OLTP, sysbench oltp_read_only

sysbench 1.0.20, 64 client threads, 10M-row table, default tuning, c5.4xlarge (16 vCPU, 64 GB RAM). Numbers approximated from the OnGres "Best practices for benchmarking with sysbench" public study; JSON property lookup added from Crunchy Data's JSONB benchmark.

Metric
Postgres
MySQL
Better
Throughput
MySQL's simpler optimizer wins on point reads.
142k qps
168k qps
MySQL
p50 latency
0.42 ms
0.34 ms
MySQL
p99 latency
Postgres has tighter tails under sustained load.
1.8 ms
2.3 ms
Postgres
CPU per query
11 µs
9 µs
MySQL
JSON property lookup p50
JSONB + GIN vs MySQL JSON functional index.
0.5 ms
1.9 ms
Postgres

Source: OnGres / sysbench + Crunchy Data JSONB benchmark ↗

When to pick neither

A different shape of problem.

  • Horizontal scale with Postgres wire compatibility
  • Mostly time-series; runs as a Postgres extension
  • ClickHouse
    Analytics, not OLTP; columnar storage wins for aggregates
  • DuckDB
    Single-machine or embedded analytics
  • SQLite
    Embedded use with low concurrent writes (under ~100/s)
  • TiDB or Vitess
    MySQL-shaped workload that needs horizontal scale
Situational picks

For specific cases.

B2B SaaS with a complex multi-tenant schema

Postgres

CHECK constraints, custom enums, JSONB for tenant metadata, and row-level security are all native. The schema will use them.

WordPress, Magento, or phpBB at scale

MySQL

These stacks were built MySQL-first. Every plugin and runbook assumes it. Going against that costs more than it saves.

Financial transactions where correctness comes before performance

Postgres

Serializable isolation, foreign keys that always work, and a planner that does not silently truncate integers all reduce the surface area for bugs.

High-write IoT ingest at 100K+ rows/s with rolling retention

TimescaleDB (a Postgres extension) or ClickHouse

Both vanilla engines choke on aggressive deletes and partition swaps at this rate. A purpose-built time-series engine is the right shape.

Small team that needs the database to just work

Either

A managed RDS or Cloud SQL instance of either runs for years untouched. The one the team already knows is the right pick.

Sources

Primary material.

Found this useful?