PostgreSQL 18 was officially released on September 25, 2025. No doubt the most consequential change is the new Asynchronous I/O (AIO) subsystem. However, this post focuses on the features that will impact developers in their day-to-day work, starting with native UUID v7 support.
Native UUID v7 Support #
PostgreSQL 18 introduces the uuidv7() function for generating UUID version 7 values. This native support almost closes the long-standing debate about whether to use SERIAL/IDENTITY types or UUIDs as primary keys. UUIDv7 combines the best of both worlds: the global uniqueness of UUIDs with the sequential nature that makes serial keys perform well.
SELECT uuidv7 ( ) ; CREATE TABLE orders ( id UUID PRIMARY KEY DEFAULT uuidv7 ( ) , customer_id INT , total DECIMAL ( 10 , 2 ) , created_at TIMESTAMP DEFAULT NOW ( ) ) ;
Previously, while PostgreSQL extensions could generate UUIDv7, the most widely used uuid-ossp extension doesn't implement v7. Lesser-known extensions that do support v7 aren't typically packaged with PostgreSQL distributions, especially on cloud providers. This meant developers wanting UUIDv7 had to implement generation logic in their applications. Native support removes this friction entirely.
VIRTUAL Generated Columns #
Generated columns were first introduced in PostgreSQL 12, but only with the STORED option, which means the generated column is stored on write and occupies disk space. Adding a STORED generated column will rewrite the entire table.
PostgreSQL 18 introduces the VIRTUAL option and makes it the default behavior for generated columns. These columns compute their values when read rather than when written. This is a more common approach, and making it the default aligns PostgreSQL with other major databases.
CREATE TABLE employees ( id SERIAL PRIMARY KEY , first_name TEXT NOT NULL , last_name TEXT NOT NULL , salary DECIMAL ( 10 , 2 ) , annual_salary DECIMAL ( 12 , 2 ) GENERATED ALWAYS AS ( salary * 12 ) VIRTUAL ) ; INSERT INTO employees ( first_name , last_name , salary ) VALUES ( 'John' , 'Doe' , 5000.00 ) , ( 'Jane' , 'Smith' , 6500.00 ) ; SELECT first_name , last_name , salary , annual_salary FROM employees ;
Virtual column advantages:
... continue reading