Postgres New Features by Version: 14 Through 18

If you're trying to figure out what changed between Postgres versions — or which one to upgrade to next — here's the short version: 14 fixed connection scaling and added pipeline mode, 15 brought MERGE, 16 opened up logical replication from standbys, 17 overhauled vacuum memory and added JSON_TABLE, and 18 shipped real asynchronous I/O along with UUIDv7 and temporal constraints. Below is what actually matters in each release, and how to think about the upgrade.

📖 Read the full guide: Postgres 14 to 18: The Best Features by Version

▶ Watch the video walkthrough: The Best Features of the Last 5 Postgres Versions
https://www.youtube.com/watch?v=EhoZpP0Jy0E

Postgres New Features by Version: 14 Through 18

Postgres 14: Connection Scaling and Pipeline Mode

Postgres 14 was a quiet-looking release that fixed a loud problem: performance under high connection counts. Before 14, servers with thousands of idle or lightly active connections took a real throughput hit. That got noticeably better here.

Other notable additions:

  • Pipeline mode in libpq — send multiple queries without waiting for each response, cutting round-trip latency for apps doing lots of small statements.
  • JSON subscriptingdata['key'] instead of data->'key', which reads more like working with a native type.
  • CTE inlining by default — WITH clauses that aren't recursive and aren't referenced multiple times now get folded into the main query plan instead of acting as an optimization fence.
  • Faster B-tree index vacuuming and reduced bloat for tables with lots of updates.

If you're still on 13 or earlier, 14 is the release where "just upgrade already" started paying for itself in raw throughput.

Postgres 15: MERGE Finally Arrives

Postgres 15's headline feature is the SQL-standard MERGE command — upsert logic that handles insert, update, and delete in one statement instead of juggling INSERT ... ON CONFLICT workarounds.

Also worth knowing:

  • Row and column filters for logical replication — publish only the rows or columns a subscriber actually needs, instead of shipping the whole table.
  • Public schema locked down by default — new databases no longer grant CREATE on public to all users. This is a security fix, but it breaks scripts that assumed the old default, so check your deploy tooling before upgrading.
  • Server-side compression for pg_basebackup, including support for zstd and LZ4, which shrinks backup windows meaningfully on large clusters.
  • Sorting performance improvements, particularly for queries with large sort operations spilling to disk.

Postgres 16: Logical Replication Grows Up

Postgres 16's biggest structural change is logical replication from physical standbys — previously, logical replication had to originate from the primary. This unlocks read-scaling and migration patterns that were awkward or impossible before.

Other changes that show up in real workloads:

  • Parallel execution for FULL and RIGHT outer joins, closing a gap where certain join types couldn't use parallel workers at all.
  • pg_stat_io — a new view that breaks down I/O by backend type and context, useful for figuring out whether your bottleneck is actually the buffer cache or the OS page cache.
  • SQL/JSON constructor and query functions (JSON_ARRAY, JSON_OBJECT, and friends), moving Postgres closer to full SQL/JSON standard support.
  • libpq load balancing — clients can now round-robin across a list of hosts instead of always hitting the first one.

Postgres 17: Vacuum Gets Rebuilt Under the Hood

Postgres 17 rewrote how vacuum manages memory, replacing the old fixed-size dead-tuple array with a structure that scales far better on large tables — vacuum runs faster and uses meaningfully less RAM doing it.

The rest of the release:

  • JSON_TABLE — turn JSON documents into relational rows directly in SQL, finishing off a feature Postgres had been missing relative to Oracle and SQL Server for years.
  • Logical replication failover support — subscribers can follow a promoted standby without needing replication slots rebuilt from scratch, which used to be a genuinely painful failure mode.
  • MERGE … RETURNING, closing a gap from the 15 release.
  • Incremental backup support in pg_basebackup, reducing the size of routine backup jobs on large databases.
  • Better B-tree bulk loading and improved planner behavior for queries with many OR'd equality conditions (turned into IN lists automatically).

Postgres 18: Async I/O and Temporal Data

Postgres 18 is the biggest architectural shift in this list. It introduces a real asynchronous I/O subsystem, letting the server issue multiple read requests without blocking a backend process on each one — a change aimed squarely at workloads bottlenecked on storage latency rather than CPU.

Alongside that:

  • UUIDv7 generation built in (uuidv7()), giving you time-ordered UUIDs without an extension — better index locality than random UUIDv4 for high-insert tables.
  • Temporal constraintsWITHOUT OVERLAPS primary keys and foreign keys, so you can enforce non-overlapping date ranges at the schema level instead of with triggers.
  • Virtual generated columns as the default generated-column type, computed on read instead of stored on disk, which saves space for columns that are cheap to derive.
  • Skip scan for B-tree indexes, letting a multicolumn index serve queries that only filter on a later column — something that previously required a separate index.
  • OAUTHBEARER support, adding modern OAuth-based authentication alongside the existing SASL mechanisms.

Which Postgres Version Should You Upgrade To?

A rough guide, assuming you're not already on the latest:

  • Still on 12 or 13 — upgrade now, not for the features, but because you're approaching or past end-of-life support and losing security patches.
  • On 14 — the jump to 16 or 17 is worth it mainly for pg_stat_io and vacuum improvements if you run large tables.
  • On 15 — 17's vacuum rewrite and incremental backups are the strongest pull; 18's async I/O matters most if storage latency is your actual bottleneck.
  • On 16 or later — you're in good shape either way; pick based on your support window rather than chasing the newest release.

The honest answer to "which version" is usually "whichever one still has an active support window and matches what your extensions support" — Postgres feature releases are yearly and each gets five years of support, so version choice is often about ecosystem compatibility (PostGIS, pgvector, TimescaleDB) more than any single headline feature.

The Part Nobody Plans For

Every major version upgrade carries a small risk that the planner behaves differently on a specific query — the new B-tree bulk loading in 17, or a changed default statistics target, can flip a plan from an index scan to a sequential scan on a table that's grown past some threshold. It rarely shows up in staging because staging data is smaller.

Keeping a before/after record of query plans and their costs across the upgrade boundary is tedious, unglamorous work — and it's the one thing that reliably catches this class of regression before production does. If you'd rather not build that tracking by hand, MyDBA does it automatically.

Upgrade for the support window first. The features you've already paid for are just a bonus.

Leave a Comment