The Engineering Revolution of UUID Version 7 (RFC 9562)
Standard Reference: IETF RFC 9562 ยง5.7 (Published May 2024, superseding RFC 4122)
RFC 9562 Structural Bit Layout
Unlike Version 4 (pure randomness) or Version 1 (Gregorian timestamp + hardware MAC), Version 7 establishes an elegant hybrid format engineered for modern database and microservice performance:
Unsigned 48-bit integer representing milliseconds elapsed since Unix epoch (Jan 1, 1970 UTC). Valid until the year 10889 AD.
4 bits set to 0111 (Version 7) + 12 bits of secure pseudorandom
entropy or sub-millisecond sequence counter.
2 bits set to 10xx (RFC 4122/9562 variant) + 62 bits of cryptographically
unguessable hardware randomness.
Provides up to 2โทโด unique combinations within the exact same millisecond per generating node, eliminating collision risk.
Why UUID v7 Fixes Database Index Fragmentation
In relational database management systems (such as PostgreSQL, MySQL InnoDB, SQLite, and Microsoft SQL Server), primary keys are stored in B-Tree (B+ Tree) indexes.
โ The UUID v4 Bottleneck
Because UUID v4 keys are completely random, every new database insert lands at an arbitrary location across the index leaf pages. Once a table grows beyond cache memory (RAM), inserting new records forces the storage engine to read random index pages from disk, split full pages in half, and rebalance the tree. This causes severe disk I/O thrashing and write amplification at scale.
โ The UUID v7 Solution
Because UUID v7 keys start with a 48-bit millisecond timestamp, newly created keys are naturally sequentially higher than previously created keys. New database inserts append cleanly to the right-most edge of the B-Tree index, maximizing buffer pool cache hit rates, preventing index fragmentation, and matching the write performance of auto-incrementing integers!
Database Schema Examples
-- PostgreSQL 17 native support:
CREATE TABLE orders (
id UUID PRIMARY KEY DEFAULT uuid_generate_v7(),
customer_id UUID NOT NULL,
total_amount NUMERIC(10, 2) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Querying by time range directly from UUID:
SELECT * FROM orders
WHERE id >= '018e4700-0000-7000-8000-000000000000';
import { v7 as uuidv7 } from 'uuid';
// Generates time-ordered RFC 9562 UUID:
const orderId = uuidv7();
console.log(orderId);
// Output: 018e4785-3b90-7f2e-831d-b54129b01f92
// Extract millisecond timestamp:
const timeMs = parseInt(orderId.slice(0, 8) + orderId.slice(9, 13), 16);
console.log(new Date(timeMs).toISOString());