I’ve been using UUIDv4 as primary keys across most of our services for a while now. They’re great for avoiding ID collisions in distributed systems, but the random ordering absolutely kills B-tree index performance on large tables. Every insert goes to a random leaf page, which means constant page splits, bloated indexes, and terrible cache hit rates.
PostgreSQL 18 just shipped with a native uuidv7() function, and I’m seriously considering migrating. For anyone unfamiliar, UUIDv7 embeds a Unix timestamp in the first 48 bits, so the generated values are naturally time-ordered. In theory, this gives you the distributed-friendliness of UUIDs with the insert performance of sequential IDs.
Here’s what I’m thinking for new tables:
CREATE TABLE orders (
id uuid DEFAULT uuidv7() PRIMARY KEY,
customer_id uuid NOT NULL,
total_amount numeric(12,2) NOT NULL,
created_at timestamptz DEFAULT now()
);
And for existing tables, something like:
-- Check if existing UUIDv4 values would sort correctly alongside new UUIDv7 values
SELECT id, uuid_extract_timestamp(id) FROM orders LIMIT 5;
-- This returns NULL for v4 UUIDs since they don't encode timestamps
My questions for anyone who’s already made this switch:
-
Did you migrate existing UUIDv4 columns to UUIDv7, or just start using v7 for new rows? Mixing versions in the same column feels wrong, but rewriting millions of PKs (and every FK that references them) sounds painful.
-
How much did your write performance actually improve on large tables? I’ve seen benchmarks showing 2-3x improvement on insert-heavy workloads, but real-world numbers would be more helpful.
-
Are you still keeping a separate
created_atcolumn, or do you extract the timestamp from the UUID withuuid_extract_timestamp()? Dropping the extra column is tempting but it feels like coupling your ID strategy to your time-tracking strategy. -
Any gotchas with ORMs? We’re using SQLAlchemy and I’m wondering if the default UUID type handling just works or if you need custom type decorators.
Running Postgres 18.1 on RDS. Biggest table is around 80M rows with UUIDv4 PKs.
Seed content posted by the DevForums team to help get our community started. Have a better answer? Jump in!