PostgreSQL 18: async I/O, faster upgrades, uuidv7(), OAuth 2.0

The PostgreSQL Global Development Group announced PostgreSQL 18 in September 2025 as the next major open-source release — still the reference platform that millions of services and almost every modern ORM (Prisma, Drizzle, TypeORM, sqlx, gorm) build against. The release is large but cohesive: most of the headline features sit on a single throughline — making the database faster and easier to upgrade without breaking the contract apps already depend on.
"The efforts of the global open source community shape every PostgreSQL release and help deliver features that meet users where their data resides." — Jonathan Katz, PostgreSQL core team (press release)
TL;DR
- Asynchronous I/O subsystem — sequential scans, bitmap heap scans, and vacuum benefit; up to 3× faster reads in benchmarked setups.
- Planner statistics survive `pg_upgrade` — no more "why are queries slow right after upgrade?" window.
- `pg_upgrade` itself is faster with parallel checks (
--jobs) and a new--swapmode. - Virtual generated columns are the default for new generated columns; stored ones can now logically replicate.
- `uuidv7()` built in for time-ordered UUIDs.
- Temporal constraints (
WITHOUT OVERLAPS,PERIODon FKs) for range-shaped uniqueness. - OAuth 2.0 server-side hooks and finer TLS 1.3 cipher control.
Asynchronous I/O
This is the headline. Until 18, Postgres did most disk reads synchronously: a backend process asked the kernel for a page, blocked on the read, and continued when the page arrived. On modern storage (NVMe, especially when the kernel can use io_uring or worker threads), that's a real bottleneck — the disk is capable of fielding many in-flight reads in parallel, but the database wasn't using that capacity.
PG 18 introduces an async I/O subsystem with three implementations selectable via the io_method GUC:
- `worker` — a pool of helper processes issue reads on behalf of backends. Portable across Linux and other Unix variants.
- `io_uring` — Linux-native, uses the kernel's modern asynchronous I/O interface. Lowest-latency option on supported kernels.
- `sync` — the legacy path, kept for compatibility and debugging.
The benefit is concentrated in three operations:
- Sequential scans on large tables.
- Bitmap heap scans that read many non-contiguous pages.
- VACUUM and
autovacuumworkers, which previously serialized I/O.
Benchmarks from the release announcement and follow-up community posts show up to 3× faster reads in workloads dominated by these patterns. Wins are smaller in OLTP-heavy workloads where queries hit the buffer cache.
Tuning advice: leave io_method = sync if you're upgrading a critical system without time to test. Switch to worker first (broadly safe), then to io_uring once you've verified your kernel supports it and your monitoring is in place.
`pg_upgrade` got better
Two pain points around in-place upgrades got addressed:
- Planner statistics carry forward. Before 18,
pg_upgradeleft you with emptypg_statistictables untilANALYZEran, which meant the planner would pick bad query plans during the gap. PG 18 preserves stats across the upgrade — the post-upgrade "why are plans weird?" window largely disappears. - Parallel checks.
pg_upgrade --jobs Nnow runs catalog checks and per-database operations in parallel. - `--swap` mode avoids copying whole data directories. On large clusters that previously took hours, the upgrade can complete in minutes.
If your operations team has scripts that pad downtime to account for slow upgrades, the budget can shrink.
Virtual generated columns
Generated columns existed in earlier versions, but only as stored (computed at write time, persisted). PG 18 ships virtual generated columns as the default for new declarations:
CREATE TABLE orders (
subtotal_cents int NOT NULL,
tax_cents int NOT NULL,
total_cents int GENERATED ALWAYS AS (subtotal_cents + tax_cents) VIRTUAL
);The total_cents column doesn't take disk space; it's computed at read time. Trade-offs:
- Storage savings for columns that derive cheaply from others.
- No write-time cost — inserts and updates skip the computation.
- Cannot be indexed directly (use expression indexes instead).
Stored generated columns are still available when you want them indexed or replicated. And speaking of replication, stored generated columns can now logically replicate, which fills a long-standing gap in logical replication.
`uuidv7()`
PG 18 ships a built-in uuidv7() function. UUIDv7 is a draft RFC for time-ordered UUIDs — the first 48 bits are a Unix-epoch millisecond timestamp, the rest is random. Two practical wins over UUIDv4:
- B-tree locality. Inserts cluster at the right edge of the index, so the database doesn't have to rebalance pages on every write.
- Sortability.
ORDER BY idreturns rows in approximate insertion order, which is often what apps actually want.
If you've been using random UUIDv4 as primary keys and watching index fragmentation grow, switch to uuidv7() for new tables.
Temporal constraints
PG 18 adds first-class support for range-shaped uniqueness through SQL standard PERIOD and WITHOUT OVERLAPS syntax:
CREATE TABLE bookings (
room_id int NOT NULL,
during tstzrange NOT NULL,
EXCLUDE USING GIST (room_id WITH =, during WITH &&)
);Foreign keys can also reference a period:
ALTER TABLE assignments
ADD FOREIGN KEY (employee_id, PERIOD during)
REFERENCES employments (id, PERIOD employed_during);This collapses a class of "do these intervals overlap?" checks that previously had to be enforced by application code or by exclusion constraints with hand-tuned operator classes.
Security: OAuth 2.0 and TLS 1.3
- OAuth 2.0 server-side hooks. PG 18 exposes the hooks needed for an external authentication library to authenticate clients via OAuth 2.0. The release ships the framework; specific identity providers (Auth0, Okta, AzureAD) are configured through extensions.
- TLS 1.3 cipher control. You can now configure TLS 1.3 cipher suites independently from TLS 1.2, which matters for compliance regimes that mandate specific cipher restrictions.
Both fit the broader theme of "Postgres makes the security work easier without forcing a particular stack".
Logical replication: the small but important bits
- Stored generated columns now logically replicate (mentioned above).
- Sequence values can be replicated.
- DDL replication remains an extension space (pg_logical, pgoutput-only-DML), but more building blocks land in core.
If you maintain a multi-region setup with logical replication, scan the changelog carefully — several edge cases got tightened.
Follow-up minors
The project ships minor versions regularly. 18.1, 18.2, and 18.3 had landed by early 2026, picking up bug fixes, security updates, and small behavioral tweaks. Keep an eye on the official release notes for your exact minor before pinning a version on a critical service.
Migration checklist
- Test on a copy with realistic data volumes before scheduling production downtime.
- Run `pg_upgrade` with
--jobsset to the number of available CPU cores;--swapif you're confident in your backups. - Verify planner stats carried over —
SELECT relname, last_analyze FROM pg_stat_user_tablesshould show recent timestamps. - Tune `io_method` in a staging environment first.
workeris the safest first step;io_uringis the higher ceiling. - Audit `pg_amcheck` output if you maintain critical clusters.
Where this connects
If your stack uses Prisma 7, the Prisma 7 release post covers the client side of the story; combined with PG 18 on the server, the read path improves at both layers. Teams on Drizzle can pair PG 18 with the Drizzle 1.0 RC for similar end-to-end gains.
References
Source / further reading: PostgreSQL Global Development Group